|
|
害羞的篮球 · 安徽这两条铁路何时开工?官方最新回复 - 川观新闻· 3 月前 · |
|
|
考研的馒头 · ASP.NET Core Blazor ...· 4 月前 · |
|
|
温柔的煎鸡蛋 · 彭兰玉:语言世界里的行者-湖南大学新闻网· 1 年前 · |
|
|
风度翩翩的镜子 · 【【专家观点】发展新质生产力要突出因地制宜】 ...· 1 年前 · |
|
|
绅士的毛巾 · 沈阳市于洪区人民政府· 1 年前 · |
我正在寻找一种方法来清理我的顶级脚本退出时的混乱。
尤其是如果我想使用
set -e
,我希望后台进程在脚本退出时会死掉。
因此,在脚本加载过程中编写脚本。运行一个
killall
(或您的操作系统上可用的任何东西)命令,该命令在脚本完成后立即执行。
要清理一些乱七八糟的东西,可以使用
trap
。它可以提供在特定信号到达时执行的内容的列表:
trap "echo hello" SIGINT
但也可用于在shell退出时执行某些操作:
trap "killall background" EXIT
它是一个内置的,所以
help trap
会给你信息(与bash一起工作)。如果你只想终止后台作业,你可以这样做
trap 'kill $(jobs -p)' EXIT
注意使用单个
'
,以防止外壳立即替换
$()
。
另一种选择是将脚本自身设置为进程组领导者,并在退出时捕获进程组上的killpg。
如果在子shell中调用jobs -p,则可能无法在所有shell中运行,除非将其输出重定向到文件而不是管道中。(我假设它最初仅用于交互用途。)
下面是什么呢?
trap 'while kill %% 2>/dev/null; do jobs > /dev/null; done' INT TERM EXIT [...]
Debian的dash shell需要调用“job”,如果当前作业("%%")丢失,它将无法更新。
更新: https://stackoverflow.com/a/53714583/302079 通过添加退出状态和清理功能改进了这一点。
trap "exit" INT TERM
trap "kill 0" EXIT
为什么要将
INT
和
TERM
转换为exit?因为两者都应该在不进入无限循环的情况下触发
kill 0
。
为什么要在
EXIT
上触发
kill 0
?因为正常的脚本退出也应该触发
kill 0
。
为什么是
kill 0
?因为嵌套的子壳也需要被杀死。这将拿下
the whole process tree
。
我根据@tokland的答案结合来自
http://veithen.github.io/2014/11/16/sigterm-propagation.html
的知识进行了修改,当我注意到如果我在运行前台进程(而不是
&
的背景)时,
trap
不会触发:
#!/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
[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
[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下工作的很好的版本。首先尝试发送send,如果没有成功,在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 &)
TrapQuit() {
# Whatever you need to clean here
KillJobs
trap TrapQuit EXIT
请注意,作业不包括子进程。
|
|
害羞的篮球 · 安徽这两条铁路何时开工?官方最新回复 - 川观新闻 3 月前 |
|
|
温柔的煎鸡蛋 · 彭兰玉:语言世界里的行者-湖南大学新闻网 1 年前 |
|
|
绅士的毛巾 · 沈阳市于洪区人民政府 1 年前 |