假设我想运行两个命令c1
和c2
,它们实际上在Linux上处理(但不修改)相同的数据。
现在我想同时启动它们,看看哪个更快完成,一旦一个进程完成,我将收集其输出(可以用c1 >> log1.txt
转储到文件中),并终止另一个处理。
请注意,两个过程的处理时间可能会有很大差异,因此可以观察到,例如一个过程需要十秒钟,而另一个过程则需要60秒。
======================更新
我尝试了以下脚本集,但它在我的计算机上导致了无限循环:
import os
os.system("./launch.sh")
launch.sh
#!/usr/bin/env bash
rm /tmp/smack-checker2
mkfifo /tmp/smack-checker2
setsid bash -c "./sleep60.sh ; echo 1 > /tmp/run-checker2" &
pid0=$!
setsid bash -c "./sleep10.sh ; echo 2 > /tmp/run-checker2" &
pid1=$!
read line </tmp/smack-checker2
printf "Process %d finished earlier\n" "$line"
rm /tmp/smack-checker2
eval kill -- -\$"pid$((line ^ 1))"
sleep60.sh
#!/usr/bin/env bash
sleep 60
sleep10.sh
#!/usr/bin/env bash
sleep 10
答案 0 :(得分:2)
使用wait -n
等待任一进程退出。忽略竞争条件和pid换行,
c1 & P1=$!
c2 & P2=$!
wait -n # wait for either one to exit
if ! kill $P1; then
# failure to kill $P1 indicates c1 finished first
kill $P2
# collect c1 results...
else
# c2 finished first
kill $P1
# collect c2 results...
fi
有关文档,请参见help wait
或man bash
。
答案 1 :(得分:1)
此代码段可以给您一些想法吗?
#!/bin/sh
runproc1() {
sleep 5
touch proc1 # file created when terminated
exit
}
runproc2() {
sleep 10
touch proc2 # file created when terminated
exit
}
# remove flags
rm proc1
rm proc2
# run processes concurrently
runproc1 &
runproc2 &
# wait until one of them is finished
while [ ! -f proc1 -a ! -f proc2 ]; do
sleep 1
echo -n "."
done
这个想法是将两个进程封装成两个函数,最后,它们触摸文件以表示计算已终止。删除用作标志的文件后,这些功能将在后台执行。最后一步是观察两个文件是否出现。到那时,任何事情都可以做:继续等待其他进程,或者杀死它。
启动此精确脚本,大约需要5秒钟,然后终止。我看到创建了文件“ proc1”,没有proc2。几秒钟后(准确地说是5),还将创建“ proc2”。这意味着即使脚本终止,任何未完成的作业也会继续运行。
答案 2 :(得分:1)
我将运行2个进程,并使它们写入共享的命名管道
他们完成之后。从命名管道读取是一项阻止操作
因此您不需要在循环内使用有趣的sleep
指令。它会
是:
#!/usr/bin/env bash
mkfifo /tmp/run-checker
(./sleep60.sh ; echo 0 > /tmp/run-checker) &
(./sleep10.sh ; echo 1 > /tmp/run-checker) &
read line </tmp/run-checker
printf "Process %d finished earlier\n" "$line"
rm /tmp/run-checker
kill -- -$$
sleep60.sh:
#!/usr/bin/env bash
sleep 60
sleep10.sh:
#!/usr/bin/env bash
sleep 10
编辑:
如果您要这样调用脚本形式的Python脚本:
#!/usr/bin/env python3
import os
os.system("./parallel.sh")
print("Done")
您将获得:
Process 1 finished earlier
./parallel.sh: line 11: kill: (-13807) - No such process
Done
这是因为kill -- -$$
试图向过程发送TERM信号
man 1 kill
中指定的组:
-n
其中n大于1。进程组n中的所有进程均为 发信号。当给出形式为'-n'的参数时 旨在表示一个过程组,或者信号必须是 首先指定,否则参数必须以“-”开头 选项,否则将被视为发送信号。
当您从终端运行parallel.sh时,它可以工作,因为$$是一个
子外壳以及过程组的PID。我用它是因为
杀死parallel.sh,process0或process1以及所有这些非常方便
他们的孩子一口气。但是,从以下位置调用parallel.sh时
Python脚本$$
不再表示进程组,而kill --
失败。
您可以像这样修改parallel.sh:
#!/usr/bin/env bash
mkfifo /tmp/run-checker
setsid bash -c "./sleep60.sh ; echo 0 > /tmp/run-checker" &
pid0=$!
setsid bash -c "./sleep10.sh ; echo 1 > /tmp/run-checker" &
pid1=$!
read line </tmp/run-checker
printf "Process %d finished earlier\n" "$line"
rm /tmp/run-checker
eval kill -- -\$"pid$((line ^ 1))"
现在从Python脚本调用时,它也将起作用。最后一行
eval kill -- -\$"pid$((line ^ 1))"
如果pid1更早完成,则杀死pid0;如果pid1更早完成,则杀死pid0 使用^二进制运算符将0转换为1,反之亦然。如果你 不喜欢它,您可以使用更详细的形式:
if [ "$line" -eq "$pid0" ]
then
echo kill "$pid1"
kill -- -"$pid1"
else
echo kill "$pid0"
kill -- -"$pid0"
fi