我希望在循环中运行多个后台进程,但只想等待所有这些进程完成,仍然允许另一个后台进程继续。
经过一些研究后,我只看到需要我列出我想要的每个进程 ID 的解决方案,wait
而不是将它们与单个进程 ID 反向匹配。看来类似的东西wait != $pid
会非常有用。
示例脚本:
#!/bin/bash
command1 &
pid=$!
for i in ${array[@]}; do
for n in $(seq 3); do
if [ $n -eq 1 ];
command2 > file &
else
command2 >> file &
fi
done
done
在此示例中,我希望等待每个进程完成,除非$pid
不必使用wait
命令列出所有进程。这可能吗?
答案1
只是有什么问题
wait
如help wait
注释:
等待由 ID(可以是进程 ID 或作业规范)标识的进程,并报告其终止状态。如果未给出 ID,则等待所有当前活动的子进程,并且返回状态为零。
您想“仍然允许另一个后台进程继续”吗?只是disown
它。按照你的例子:
command1 & disown %1
command2 & command2 & command2 &
wait
答案2
正如其他人所说,没有任何方法可以等待“不是”进程 ID。然而,这种代码模式对我来说似乎并没有那么糟糕,所以我将其作为实现您所追求的目标的建议方法提供。
它使用 Bash 数组,然后您可以将其作为列表提供给命令wait
。
例子
示例代码的修改版本,cmd.bash
.
!/bin/bash
array[0]=1
array[0]=2
sleep 30 &
pid=$!
pidArr=()
for i in ${array[@]}; do
for n in $(seq 3); do
if [ $n -eq 1 ]; then
sleep 31 > file &
pidArr+=($!)
else
sleep 32 >> file &
pidArr+=($!)
fi
done
done
echo ${pidArr[@]}
我sleep
在本例中替换了命令,只是为了模拟一些我们可以在后台运行的长时间运行的作业。他们除了充当替身之外,与此无关。
最后的命令也echo
纯粹是为了让我们可以看到 for 循环完成时会发生什么。最终我们将用实际wait
命令替换它,但我们不要超前。
示例运行 #1
那么让我们运行我们的程序,看看会发生什么。
$ ./cmd.bash
24666 24667 24668
现在如果我们检查ps
:
$ ps -eaf|grep sleep
saml 24664 1 0 22:28 pts/9 00:00:00 sleep 30
saml 24666 1 0 22:28 pts/9 00:00:00 sleep 31
saml 24667 1 0 22:28 pts/9 00:00:00 sleep 32
saml 24668 1 0 22:28 pts/9 00:00:00 sleep 32
如果我们稍等一下,这些最终都会完成。但这表明,如果我们将进程 ID 添加到数组中,echo
之后就可以将它们取出。
例子#2
因此,现在让我们更改该echo
行并换入一行wait
,如下所示:
wait ${pidArr[@]}
现在,当我们运行修改后的版本时,我们看到它正在等待所有进程 ID:
$ ./cmd.bash
...约 30 秒后
$
我们得到提示。这样我们就顺利的等待了所有的进程。快速检查ps
:
$ ps -eaf|grep sleep
$
所以它起作用了。