在背景運行多個程式並檢查它們的返回值

在背景運行多個程式並檢查它們的返回值

假設我想同時運行幾個(比如說三個)程序,就像這樣

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 ...,並以類似的方式獲取退出代碼,但您將不知道結束的是哪個進程,但如果您只需要知道是否有失敗,那麼它很有用。

相關內容