假设我想同时运行几个(比如说三个)程序,就像这样
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 ...
,并以类似的方式获取退出代码,但您将不知道结束的是哪个进程,但如果您只需要知道是否有失败,那么它很有用。