我有一个 Bash 脚本(Bash 3.2、Mac OS X 10.8),它并行调用多个 Python 脚本,以便更好地利用多个内核。每个 Python 脚本都需要很长时间才能完成。
问题是,如果我在 Bash 脚本中间按 Ctrl+C,Python 脚本实际上并没有被杀死。我怎样才能编写 Bash 脚本,以便杀死它也会杀死它所有的背景孩子?
这是我原来的“简化测试用例”。不幸的是,我似乎已经减少了很多,以至于它不再证明问题了;我的错。
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
这是一个完整的测试用例,仍然高度简化,但希望这个可以证明问题。它可以在我的机器上重现......但是,两天前我认为旧的测试用例可以在我的机器上重现,而今天它绝对不会。
#!/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!"
still going
即使在 Ctrl+C 之后,此代码也会继续打印。但是,如果我将Ctrl+C&
从外process
移到内(即:)./work.sh $1 &
,则 Ctrl+C 将按预期工作。我完全不明白这个!
在我的真实脚本中,process
包含多个命令,并且命令是长时间运行的,必须按顺序运行;所以我不知道在那种情况下如何“移动&
内部”。process
我确信这是可能的,但它必须是不平凡的。
$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.
编辑:非常感谢@AlanCurry 教我一些 Bash 的东西。不幸的是,我仍然不明白我的示例中到底发生了什么,但这实际上是一个有争议的问题,因为 Alan还很有帮助地指出,对于我现实世界的并行化问题,Bash 是错误的工具,我应该使用一个简单的生成文件make -j3
!make
尽可能并行运行,并且完全理解 Ctrl+C;问题已解决(即使问题未得到解答)。