Bash 中的 wait 指令是管理 shell 腳本進程的強大工具。它主要用於暫停腳本的執行,直到指定的後台程序完成。此命令在啟動多個背景作業並需要在繼續執行進一步任務之前同步其完成的腳本中非常方便。 wait 指令可套用於單一進程 ID (PID) 或等待目前 shell 會話啟動的所有背景進程。透過使用等待,您可以確保腳本僅在特定任務完全完成時才繼續前進,從而使您的自動化流程更加可靠和有效率。
本指南將提供在各種場景中使用 wait 命令的實際範例,幫助您了解如何有效管理 Bash 腳本中的背景進程。
了解 Bash wait 指令
Bash 中的 wait 指令是內建函數,它會暫停目前 shell 的執行,直到指定的作業完成。然後它會返回它正在等待的命令的退出狀態。該命令在 shell 執行環境中起著至關重要的作用,因此它內建於大多數 shell 中。
wait指令的一般語法如下:
wait [ID]
在此上下文中,ID 表示進程或作業 ID。如果未指定 ID,則 wait 指令將暫停,直到所有子背景作業完成。 wait 指令傳回它所等待的最後一個指令的退出狀態。
例如,要暫停 PID 7654 的背景進程,您可以使用:
wait 7654
如果指定了多個進程,wait 命令將暫停,直到它們完成。
使用 bash wait 指令導航作業規範
作業是使用作業規格 (jobspec) 來指定的,作業規格指的是構成作業的流程。作業規格以百分比符號開頭,後面跟著作業編號 (%n)。這是一個例子:
rsync -a /home /tmp/home &
該命令在後台運行。 shell 作業 ID(括在括號中)和進程 ID 將顯示在您的終端上。若要暫停作業,請執行 wait 指令,然後執行作業規格:
wait %2
將 -n 選項與 bash wait 指令結合使用
-n 選項允許 wait 命令僅在給定 PID 或作業規範中的單一作業完成時暫停,並返回其退出狀態。如果未提供參數,則 wait -n 等待任何背景作業完成並傳回作業退出狀態。
wait -n 45432 54346 76573
上例中,wait -n 只列印最先退出的作業的返回狀態;它不顯示作業的 PID。如果要取得返回退出狀態的作業 PID 或作業規範,請使用 -p
將其指派給變數的選項:
wait -p job_id -n 45432 54346 76573
-p 選項是在 Bash 5.1 中引入的。使用較舊的 Bash 版本將導致“無效選項”錯誤。
使用 bash wait 指令探索 -f 選項
-f 選項指示在返回其退出代碼之前等待每個 PID 或作業規範終止,而不是在作業狀態變更時返回。此選項僅在啟用作業控制時有效,預設僅針對互動式提示啟用作業控制。
wait指令的實際例子
wait 指令通常用在產生並行執行的子程序的 shell 腳本中。為了說明該命令的工作原理,我們建立以下腳本:
#!/bin/bash
sleep 30 &
process_id=$!
echo "PID: $process_id"
wait $process_id
echo "Exit status: $?"
讓我們逐行分解程式碼:
- 第一行 shebang 告訴作業系統使用哪個解釋器來解析檔案的其餘部分。
- 我們使用 sleep 指令來模擬耗時的後台進程。
- $!是一個內部 Bash 變量,用於儲存最後一次在背景運行的作業的 PID。在此範例中,這是 sleep 指令的 PID。我們將 PID 儲存在變數 (process_id) 中。
- PID 號碼被列印。
- PID 被傳遞給等待命令,該命令將暫停,直到睡眠命令完成。
- 列印等待指令的退出狀態。 $?是一個內部 Bash 變量,保存最後執行的命令的退出狀態。
如果運行該腳本,它將列印如下內容:
PID: 36353
Exit status: 0
這是使用 -n 選項的範例:
#!/bin/bash
sleep 3 &
sleep 30 &
sleep 5 &
wait -n
echo "First job completed."
wait
echo "All jobs completed."
當腳本執行時,它會產生 3 個後台進程。 wait -n 暫停,直到第一個作業完成並列印 echo 語句。等待所有子後台作業完成。
First job completed.
All jobs completed.
最後一個範例解釋了 -f 選項。打開終端機並運作:
sleep 3600 &
[1] 46671
wait 46671
打開另一個終端並使用kill命令停止進程:
kill -STOP 46671
一旦進程狀態發生變化,等待命令就會完成,並返回進程退出碼。
現在,重複相同的步驟,但這次使用 wait -f $pid:
sleep 3600 &
wait -f 46671
從另一個終端停止該進程:
kill -STOP 46671
這次,等待命令將不會完成。它將運行直到睡眠進程終止。
wait指令的高階用法
在管理腳本中的多個進程時,wait 命令變得特別有用。它允許您控制執行流程並確保特定流程在其他流程開始之前已完成。讓我們深入研究一些更複雜的範例來說明這一點。
Bash 等待多個進程
考慮一個場景,多個進程在背景運行,您必須在完成它們後才採取行動。以下是如何使用 wait 指令來實現此目的:
#!/bin/bash
echo "Starting process 1..."
sleep 10 &
pid1=$!
echo "Starting process 2..."
sleep 15 &
pid2=$!
echo "Starting process 3..."
sleep 20 &
pid3=$!
echo "Waiting for processes to complete..."
wait $pid1 $pid2 $pid3
echo "All processes completed."
此腳本啟動三個後台進程,分別休眠 10、15 和 20 秒。我們將每個進程的 PID 儲存在一個變數中。然後,我們使用 wait 命令並將所有三個 PID 作為參數。該腳本將在等待命令處暫停,直到所有三個進程完成。
使用帶有循環的 Bash wait
您也可以使用 wait 和循環來管理多個進程。這是一個例子:
#!/bin/bash
for i in {1..5}
do
echo "Starting process $i..."
sleep $i &
pids[${i}]=$!
done
echo "Waiting for processes to complete..."
for pid in ${pids[*]}; do
wait $pid
done
echo "All processes completed."
在此腳本中,我們在循環中啟動五個後台進程。每個進程都會休眠幾秒鐘,其時間等於其在循環中的索引。我們將每個進程的 PID 儲存在一個陣列中。啟動所有進程後,我們循環遍歷數組並使用 wait 命令單獨暫停每個進程。該腳本將在每個等待命令處暫停,直到相應的程序完成。
結論
Bash 中的 wait 指令對於同步腳本中的後台程序至關重要。透過了解如何使用等待,您可以更精確地控制腳本流程,確保任務以所需順序完成。無論您是處理多個背景作業,還是必須確保特定進程在繼續之前完成,wait 命令都可以幫助您實現更可靠和可預測的腳本行為。考慮將等待整合到腳本中以增強流程管理並提高整體腳本效率。