所以我有一个while循环遍历包含名称的文本文件,然后在列表上执行后台进程。这一切都很好,但当它结束时,我需要按Ctrl-C。一旦所有进程完成后,我如何执行SIGINT,因此我不必ctrl-c?杀死在while循环后台进程中创建的PID
我需要在每个单独的过程中完成吗?或者我可以通过使用像睡觉这样的循环来做到这一点?
这是我目前有的,但不是很有效。
while read BAR; do foo $BAR & done < bars.txt; pid=$!; wait; kill pid
所以我有一个while循环遍历包含名称的文本文件,然后在列表上执行后台进程。这一切都很好,但当它结束时,我需要按Ctrl-C。一旦所有进程完成后,我如何执行SIGINT,因此我不必ctrl-c?杀死在while循环后台进程中创建的PID
我需要在每个单独的过程中完成吗?或者我可以通过使用像睡觉这样的循环来做到这一点?
这是我目前有的,但不是很有效。
while read BAR; do foo $BAR & done < bars.txt; pid=$!; wait; kill pid
现在你只收集最后 PID,所有你的后台进程不会的PID。
如果您收集的PID,您可以单独等待他们 - 它可以让你检查单个作业是否失败,或看到它们中的哪一个实际上并没有完成:
pids=()
while read bar; do
foo "$bar" & pids+=("$!")
done < bars.txt
for pid in "${pids[@]}"; do
echo "Checking exit status of $pid..."
if wait "$pid"; then
echo "$pid succeeded!"
else
echo "$pid failed!"
fi
done
如果你想跟踪哪些具体值是成功还是失败处理,你可以做得更好(使用bash 4.0或更高版本):
declare -A pids=()
while read -r bar; do
foo "$bar" & pids[$!]="$bar"
done < bars.txt
for pid in "${!pids[@]}"; do
bar=${pids[$pid]}
echo "Checking exit status of $pid (processing value $bar)..."
if wait "$pid"; then
echo "$pid (for $bar) succeeded!"
else
echo "$pid (for $bar) failed!"
fi
done
在上述任何一种情况下,wait
的每个调用都负责在相应的PID退出后返回。因此,当所有后台任务都退出时,脚本将自行退出。
最后,力你的孩子退出,你可以建立,是以PID列表的优势的信号处理程序:
shutdown() { kill "${pids[@]}"; } # or "${!pids[@]}" for the second example
trap shutdown 0
如果你真的想要一个班轮,你可以围绕以下逻辑构建它(格式化以提高可读性)。
while -r read BAR
do
foo "$BAR" &
done < bars.txt
wait
这将等待所有后台任务完成(包括执行此命令之前启动的任何后台任务)。这有点粗糙(CharlesDuffy提出了一个解决方案,可以更好地跟踪任务),但它有足够短的单线程的可疑优势。
while -r read BAR ; do foo "$BAR" & done < bars.txt ; wait
杀作业启动他们之后(我不清楚你为什么会想这样做),你也许可以做这样的事情:
while -r read BAR ; do foo "$BAR" & done < bars.txt ; kill $(jobs -p)
再次,这将标志着所有后台工作,不仅仅是你刚刚发布的工作。
不幸的是,我的后台进程不能自行退出 –
随着GNU并行它看起来像这样:
parallel -j0 foo {} < bars.txt
echo $? jobs failed
如果你离开了-j0
它将运行每个CPU核心一个作业。
如果您需要确切的作业失败知道,你可以使用一个joblog:
parallel --joblog jl -j0 foo {} < bars.txt
cat jl
它还确保不同作业中的输出不会混合在一起,因此,如果您使用的输出,保证您你不会从两个不同的工作中获得半条命。
GNU Parallel是一个通用的并行程序,可以很容易地在同一台机器上或在您拥有ssh访问权限的多台机器上并行运行作业。
如果你想在4个CPU上运行32个不同的工作岗位,并行化直接的方式是在每个CPU上运行8个作业:
GNU并行,而不是产生一个新的进程时,一个完成 - 保持CPU的活跃,从而节省了时间:
安装
您应该在您的软件包管理器中安装GNU Parallel,但是如果您的发行版没有打包GNU Parallel,则可以执行个人安装,但不需要root访问权限。它可以在10秒内通过这样来完成:
(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash
对于其他安装选项见http://git.savannah.gnu.org/cgit/parallel.git/tree/README
了解更多
查看更多的例子:http://www.gnu.org/software/parallel/man.html
观看介绍视频: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
走过t他教程:http://www.gnu.org/software/parallel/parallel_tutorial.html
订阅邮件列表,以获得支持:https://lists.gnu.org/mailman/listinfo/parallel
不,我应该这样做,但是反正有做在一个“衬”,所以我没有执行一份文件?像我可以把等待在循环中然后杀死PID?或者这只是让它再次同步? –
备份一下 - 为什么“杀死”呢?当我读到这个问题时,你的后台进程会自行退出,唯一的问题是调用它们的脚本不在退出......对吗? –
如果你想要一个处理并行进程的单线程,顺便说一句,你可能更好的是'xargs -P'或者GNU parallel。例如,一次最多可运行16个进程:'xargs -d $'\ n'-P 16 foo