我正在寻找一种方法来清理混乱时,我的顶级脚本退出。
特别是如果我想使用set -e,我希望后台进程在脚本退出时结束。
我正在寻找一种方法来清理混乱时,我的顶级脚本退出。
特别是如果我想使用set -e,我希望后台进程在脚本退出时结束。
当前回答
脚本的加载。运行一个killall(或操作系统上可用的任何命令)命令,该命令在脚本完成后立即执行。
其他回答
为了清理一些混乱,陷阱可以使用。它可以提供特定信号到达时执行的内容列表:
trap "echo hello" SIGINT
但如果shell退出,也可以用来执行一些东西:
trap "killall background" EXIT
它是内置的,所以帮助陷阱会给你信息(适用于bash)。如果你只想消灭后台工作,你可以做到
trap 'kill $(jobs -p)' EXIT
注意使用单个',以防止shell立即替换$()。
我把@tokland的回答与http://veithen.github.io/2014/11/16/sigterm-propagation.html的知识相结合,当我注意到如果我正在运行一个前台进程(不是后台的&),陷阱不会触发:
#!/bin/bash
# killable-shell.sh: Kills itself and all children (the whole process group) when killed.
# Adapted from http://stackoverflow.com/a/2173421 and http://veithen.github.io/2014/11/16/sigterm-propagation.html
# Note: Does not work (and cannot work) when the shell itself is killed with SIGKILL, for then the trap is not triggered.
trap "trap - SIGTERM && echo 'Caught SIGTERM, sending SIGTERM to process group' && kill -- -$$" SIGINT SIGTERM EXIT
echo $@
"$@" &
PID=$!
wait $PID
trap - SIGINT SIGTERM EXIT
wait $PID
它工作的例子:
$ bash killable-shell.sh sleep 100
sleep 100
^Z
[1] + 31568 suspended bash killable-shell.sh sleep 100
$ ps aux | grep "sleep"
niklas 31568 0.0 0.0 19640 1440 pts/18 T 01:30 0:00 bash killable-shell.sh sleep 100
niklas 31569 0.0 0.0 14404 616 pts/18 T 01:30 0:00 sleep 100
niklas 31605 0.0 0.0 18956 936 pts/18 S+ 01:30 0:00 grep --color=auto sleep
$ bg
[1] + 31568 continued bash killable-shell.sh sleep 100
$ kill 31568
Caught SIGTERM, sending SIGTERM to process group
[1] + 31568 terminated bash killable-shell.sh sleep 100
$ ps aux | grep "sleep"
niklas 31717 0.0 0.0 18956 936 pts/18 S+ 01:31 0:00 grep --color=auto sleep
一个可以在Linux、BSD和MacOS x下工作的不错的版本。首先尝试发送SIGTERM,如果不成功,10秒后终止进程。
KillJobs() {
for job in $(jobs -p); do
kill -s SIGTERM $job > /dev/null 2>&1 || (sleep 10 && kill -9 $job > /dev/null 2>&1 &)
done
}
TrapQuit() {
# Whatever you need to clean here
KillJobs
}
trap TrapQuit EXIT
请注意,作业不包括子代进程。
trap 'kill $(jobs -p)'退出
我只会对Johannes的答案做一些小改动,并使用jobs -pr将kill限制为正在运行的进程,并在列表中添加更多的信号:
trap 'kill $(jobs -pr)' SIGINT SIGTERM EXIT
脚本的加载。运行一个killall(或操作系统上可用的任何命令)命令,该命令在脚本完成后立即执行。