2017-04-17 108 views
1

所以我有一个while循环遍历包含名称的文本文件,然后在列表上执行后台进程。这一切都很好,但当它结束时,我需要按Ctrl-C。一旦所有进程完成后,我如何执行SIGINT,因此我不必ctrl-c?杀死在while循环后台进程中创建的PID

我需要在每个单独的过程中完成吗?或者我可以通过使用像睡觉这样的循环来做到这一点?

这是我目前有的,但不是很有效。

while read BAR; do foo $BAR & done < bars.txt; pid=$!; wait; kill pid

回答

1

现在你只收集最后 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 
+0

不,我应该这样做,但是反正有做在一个“衬”,所以我没有执行一份文件?像我可以把等待在循环中然后杀死PID?或者这只是让它再次同步? –

+0

备份一下 - 为什么“杀死”呢?当我读到这个问题时,你的后台进程会自行退出,唯一的问题是调用它们的脚本不在退出......对吗? –

+0

如果你想要一个处理并行进程的单线程,顺便说一句,你可能更好的是'xargs -P'或者GNU parallel。例如,一次最多可运行16个进程:'xargs -d $'\ n'-P 16 foo

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) 

再次,这将标志着所有后台工作,不仅仅是你刚刚发布的工作。

+0

不幸的是,我的后台进程不能自行退出 –

1

随着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个作业:

Simple scheduling

GNU并行,而不是产生一个新的进程时,一个完成 - 保持CPU的活跃,从而节省了时间:

GNU Parallel scheduling

安装

您应该在您的软件包管理器中安装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