在后台运行多个程序并检查它们的返回值

在后台运行多个程序并检查它们的返回值

假设我想同时运行几个(比如说三个)程序,就像这样

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 ...,并以类似的方式获取退出代码,但您将不知道结束的是哪个进程,但如果您只需要知道是否有失败,那么它很有用。

相关内容