Bash 脚本在 Ctrl+C 上杀死背景(孙)子

标签 bash shell process wait kill

我有一个 Bash 脚本(Bash 3.2,Mac OS X 10.8)可以并行调用多个 Python 脚本,以便更好地利用多个内核。每个 Python 脚本都需要很长时间才能完成。

问题是,如果我在 Bash 脚本中间按下 Ctrl+C,Python 脚本实际上并没有被杀死。我如何编写 Bash 脚本,以便杀死它也会杀死它的所有背景 child ?

这是我原来的“简化测试用例”。不幸的是,我似乎已经将它减少了太多,以至于它不再显示问题;我的错误。

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 之后也是如此。但是,如果我将 & 从外部 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 的简单 makefile! make 在可能的情况下并行运行,并且完全理解 Ctrl+C;问题已解决(即使问题未得到解答)。

最佳答案

我明白了!您所要做的就是摆脱那个 python SIGINT 处理程序。

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 上杀死背景(孙)子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11696691/

相关文章:

mysql - 由于 mysql 查询,无法在 shell 脚本中获取输出

linux - Bash 内置哈希和命令搜索

linux shell搜索数字之间不出现的数字

node.js - Gitlab-ci 脚本和 ssh 中的 Nvm

python - 文件夹+数据库的备份 - Python

bash - 如何将 env 输出为可运行的 shell 脚本

带有模式的 bash 定位命令

process - 从 Elm 进程接收消息

c# - 使用 Linq 将进程名称与 XML 列表进行比较

Python 多处理和套接字未关闭