假設我想同時運行幾個(比如說三個)程序,就像這樣
program1 & program2 & program3 &
如果我想知道它們pid's
,我認為最好的方法是儲存它們,就像這樣
program1 &
pid1=$!
program2 &
pid2=$!
...
但現在,如果我想知道它們是否已經結束,如果是,它們會回傳什麼值呢?像這樣的東西:
if [ program1 has ended ]; then
do something with its return value
fi
任何幫助將不勝感激
答案1
# launch child process in background
launch_child_process &
# grab child's pid and store it (use array if several)
pid=$!
# later, wait for termination
wait $pid
# show return code from wait, which is actually the return code of the child
echo "Child return code:" $?
對於多個子進程,您當然可以循環等待每個 pid 並收集相應的返回碼。當最後一個子進程結束時,您就可以退出該循環。
答案2
一個簡單的解決方案是將訊息寫入日誌文件
比如說,對於程序 1,執行以下操作:
#!/bin/bash
.
.
your stuff
.
.
end_time==$(date)
echo "program1 ended at $end_time" > program1_log
另一個想法是創建一個空文件來標記進程結束
#!/bin/bash
.
.
your stuff
.
.
echo $? > /some/path/program1_ended #storing the exit value
#disadvantage is that you can't verify if intermediate commands failed.
然後檢查做
if [ -e /some/path/program1_ended ]
then
exit_status=$( </some/path/program1_ended )
rm /some/path/program1_ended #Deleting the file, getting ready for next run
.
.
Do something
else
echo "program1 has not ended yet"
fi
答案3
POSIX sh 不太擅長處理多個後台程序。基本工具是wait
內建工具,它會阻塞直到後台程序退出。但wait
毫無爭議地等到全部後台進程已退出,並傳回最後退出進程的退出狀態;其他子行程的退出狀態遺失。
您可以為 SIGCHLD 設定陷阱,這是當進程的子程序退出時引發的訊號。每當子進程退出時就會執行程式碼。但是,您不一定知道哪個子進程退出或其傳回狀態是什麼。不同的外殼表現不同。
ATT ksh93(不是 mksh 或 pdksh!)是常見 shell 中唯一能夠有效處理 SIGCHLD 陷阱的 shell。它設定$!
退出進程的 PID 及其$?
返回狀態。
#!/bin/ksh
trap 'Process $! (${subprocesses[$!]}) exited with status $?' CHLD
typeset -A subprocesses
program1 & subprocesses[$!]='program1'
program2 & subprocesses[$!]='program2'
wait
如果您使用其他 shell,請將任何後處理放入子進程中。
#!/bin/sh
{ program1; echo "program1 exited with status $?"; } &
{ program2; echo "program2 exited with status $?"; } &
wait
或使用更強大的語言,例如 Perl、Python、Ruby 等。
答案4
如果您大致知道進程將按什麼順序結束,則可以使用wait <pid>
等待它退出,並且該wait
命令將繼承等待進程的退出狀態。例如
if wait $pid1
then echo "$pid1 was ok"
else echo "$pid1 failed with code $?"
fi
如果您不知道順序,您可以使用 等待其中任何一個wait -n $pid1 $pid2 ...
,並以類似的方式獲取退出代碼,但您將不知道結束的是哪個進程,但如果您只需要知道是否有失敗,那麼它很有用。