bash 当 shell 脚本被杀死时终止正在运行的命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1644856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Terminate running commands when shell script is killed
提问by nos
For testing purposes I have this shell script
出于测试目的,我有这个 shell 脚本
#!/bin/bash
echo $$
find / >/dev/null 2>&1
Running this from an interactive terminal, ctrl+c will terminate bash, and the find command.
从交互式终端运行它,ctrl+c 将终止 bash 和 find 命令。
$ ./test-k.sh
13227
<Ctrl+C>
$ ps -ef |grep find
$
Running it in the background, and killing the shell only will orphan the commands running in the script.
在后台运行它,杀死 shell 只会孤立脚本中运行的命令。
$ ./test-k.sh &
[1] 13231
13231
$ kill 13231
$ ps -ef |grep find
nos 13232 1 3 17:09 pts/5 00:00:00 find /
$
I want this shell script to terminate all its child processes when it exits regardless of how it's called. It'll eventually be started from a python and java application - and some form of cleanup is needed when the script exits - any options I should look into or any way to rewrite the script to clean itself up on exit?
我希望这个 shell 脚本在退出时终止它的所有子进程,而不管它是如何调用的。它最终将从 python 和 java 应用程序启动 - 当脚本退出时需要某种形式的清理 - 我应该研究的任何选项或任何重写脚本以在退出时清理自身的方法?
采纳答案by Carl Norum
I would do something like this:
我会做这样的事情:
#!/bin/bash
trap : SIGTERM SIGINT
echo $$
find / >/dev/null 2>&1 &
FIND_PID=$!
wait $FIND_PID
if [[ $? -gt 128 ]]
then
kill $FIND_PID
fi
Some explanation is in order, I guess. Out the gate, we need to change some of the default signal handling. :is a no-op command, since passing an empty string causes the shell to ignore the signal instead of doing something about it (the opposite of what we want to do).
我想应该有一些解释。走出大门,我们需要更改一些默认的信号处理。 :是一个无操作命令,因为传递一个空字符串会导致 shell 忽略该信号而不是对其进行处理(与我们想要做的相反)。
Then, the findcommand is run in the background (from the script's perspective) and we call the waitbuiltin for it to finish. Since we gave a real command to trapabove, when a signal is handled, waitwill exit with a status greater than 128. If the process waited for completes, waitwill return the exit status of that process.
然后,find命令在后台运行(从脚本的角度来看),我们调用wait内置函数来完成它。由于我们给了trap上面一个真正的命令,当一个信号被处理时,wait会以大于 128 的状态退出。如果进程waited for 完成,wait将返回该进程的退出状态。
Last, if the waitreturns that error status, we want to killthe child process. Luckily we saved its PID. The advantage of this approach is that you can log some error message or otherwise identify that a signal caused the script to exit.
最后,如果wait返回那个错误状态,我们想要kill子进程。幸运的是,我们保存了它的 PID。这种方法的优点是您可以记录一些错误消息或以其他方式识别导致脚本退出的信号。
As others have mentioned, putting kill -- -$$as your argument to trapis another option if you don't care about leaving any information around post-exit.
正如其他人所提到的,如果您不关心在退出后留下任何信息,那么将其kill -- -$$作为您的论点trap是另一种选择。
For trapto work the way you want, you do need to pair it up with wait- the bashman page says "If bashis waiting for a command to complete and receives a signal for which a traphas been set, the trapwill not be executed until the command completes." waitis the way around this hiccup.
为了trap以您想要的方式工作,您确实需要将其与wait-bash手册页说“如果 bash正在等待命令完成并接收到trap已为其设置的信号,则trap在命令完成之前不会执行.” wait是解决这个问题的方法。
You can extend it to more child processes if you want, as well. I didn't really exhaustively test this one out, but it seems to work here.
如果需要,您也可以将其扩展到更多子进程。我并没有真正详尽地测试这个,但它似乎在这里工作。
$ ./test-k.sh &
[1] 12810
12810
$ kill 12810
$ ps -ef | grep find
$
回答by Patrick
Was looking for an elegant solution to this issue and found the following solution elsewhere.
正在寻找解决此问题的优雅解决方案,并在其他地方找到了以下解决方案。
trap 'kill -HUP 0' EXIT
My own man pages say nothing about what 0means, but from digging around, it seems to mean the current process group. Since the script get's it's own process group, this ends up sending SIGHUP to all the script's children, foreground and background.
我自己的手册页没有说明什么0意思,但是从周围挖掘来看,它似乎是指当前的进程组。由于脚本获取了它自己的进程组,因此最终会向脚本的所有子进程、前台和后台发送 SIGHUP。
回答by pixelbeat
Send a signal to the group.
So instead of kill 13231do:
向小组发送信号。所以,而不是kill 13231做:
kill -- -13231
If you're starting from python then have a look at: http://www.pixelbeat.org/libs/subProcess.pywhich shows how to mimic the shell in starting and killing a group
如果您从 python 开始,请查看:http: //www.pixelbeat.org/libs/subProcess.py,其中显示了如何在启动和终止组时模拟 shell
回答by teh_senaus
@Patrick's answer almost did the trick, but it doesn't work if the parentprocess of your currentshell is in the same group (it kills the parent too).
@Patrick 的回答几乎可以解决问题,但是如果当前shell的父进程在同一个组中,它就不起作用(它也会杀死父进程)。
I found this to be better:
我发现这更好:
trap 'pkill -P $$' EXIT
trap 'pkill -P $$' EXIT
See herefor more info.
请参阅此处了解更多信息。
回答by Vlad the Impala
Just add a line like this to your script:
只需在您的脚本中添加这样的一行:
trap "kill $$" SIGINT
You might need to change 'SIGINT' to 'INT' on your setup, but this will basically kill your process and all child processes when you hit Ctrl-C.
您可能需要在设置中将“SIGINT”更改为“INT”,但这基本上会在您按 Ctrl-C 时终止您的进程和所有子进程。
回答by ennuikiller
The thing you would need to do is trap the kill signal, kill the find command and exit.
您需要做的是捕获终止信号,终止 find 命令并退出。

