bash脚本杀背景(大)上按Ctrl + C儿童 [英] Bash script kill background (grand)children on Ctrl+C
问题描述
我有一个Bash脚本(猛砸3.2的Mac OS X 10.8)调用多个并行的Python脚本,以便更好地利用多个内核。每个Python脚本需要很长的时间才能完成。
I have a Bash script (Bash 3.2, Mac OS X 10.8) that invokes multiple Python scripts in parallel in order to better utilize multiple cores. Each Python script takes a really long time to complete.
问题是,如果我在Bash脚本中间按Ctrl + C,Python的脚本实际上没有被杀死。我怎么能写的Bash脚本,以便杀死它也将杀死所有的背景的孩子?
The problem is that if I hit Ctrl+C in the middle of the Bash script, the Python scripts do not actually get killed. How can I write the Bash script so that killing it will also kill all its background children?
下面是我原来的降低测试案例。不幸的是我似乎已经减少了这么多,它不再演示该问题;我的错误。
Here's my original "reduced test case". Unfortunately I seem to have reduced it so much that it no longer demonstrates the problem; my mistake.
set -e
cat >work.py <<EOF
import sys, time
for i in range(10):
time.sleep(1)
print "Tick from", sys.argv[1]
EOF
function process {
python ./work.py $1 &
}
process one
process two
wait
下面是一个完整的测试情况下,仍然高度降低了,但希望这一次会说明问题。它再现了我的机器上......不过呢,前两天我还以为的老的测试案例重现我的机器上,而今天它绝对没有。
Here's a complete test case, still highly reduced, but hopefully this one will demonstrate the problem. It reproduces on my machine... but then, two days ago I thought the old test case reproduced on my machine, and today it definitely doesn't.
#!/bin/bash -e
set -x
cat >work.sh <<EOF
for i in 0 1 2 3 4 5 6 7 8 9; do
sleep 1; echo "still going"
done
EOF
chmod +x work.sh
function kill_all_jobs { jobs -p | xargs kill; }
trap kill_all_jobs SIGINT
function process {
./work.sh $1
}
process one &
wait $!
echo "All done!"
这code继续打印仍在
即使按Ctrl + C。但是,如果我移动&安培;
从外面过程
到内(即: ./工作$的.sh 1安培;
),然后按Ctrl + C按预期工作。我根本不明白这一点!
This code continues to print still going
even after Ctrl+C. But if I move the &
from outside process
to inside (i.e.: ./work.sh $1 &
), then Ctrl+C works as expected. I don't understand this at all!
在我的真实脚本中,过程
包含多个命令,这些命令是长时间运行的,必须按顺序运行;所以我不知道如何移动&安培;
在过程
在这种情况下。我敢肯定,这是可能的,但一定是不平凡的。
In my real script, process
contains more than one command, and the commands are long-running and must run in sequence; so I don't know how to "move the &
inside process
" in that case. I'm sure it's possible, but it must be non-trivial.
$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.
编辑:非常感谢@AlanCurry教我一些东西猛砸。不幸的是我还是不明白到底发生了什么事在我的例子,但它实际上是一个有争议的问题,因为阿兰的也的有益指出,对于我的现实世界并行化的问题,Bash是错误的工具和我应该使用一个简单的makefile与使-j3
! 制作
运行东西并联在可能的情况,也理解Ctrl + C键完美;问题解决了(即使无法解决的问题)。
Many thanks to @AlanCurry for teaching me some Bash stuff. Unfortunately I still don't understand exactly what's going on in my examples, but it's practically a moot point, as Alan also helpfully pointed out that for my real-world parallelization problem, Bash is the wrong tool and I ought to be using a simple makefile with make -j3
! make
runs things in parallel where possible, and also understands Ctrl+C perfectly; problem solved (even though question unanswered).
推荐答案
我知道了!所有你所要做的就是摆脱蟒蛇SIGINT处理程序。
I got it! All you have to do is get rid of that python SIGINT handler.
cat >work.py <<'EOF'
import sys, time, signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
for i in range(10):
time.sleep(1)
print "Tick from", sys.argv[1]
EOF
chmod +x work.py
function process {
python ./work.py $1
}
process one &
wait $!
echo "All done!"
这篇关于bash脚本杀背景(大)上按Ctrl + C儿童的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!