有没有什么方法可以在 Bash 中并行运行两个命令,这样,如果 shell 被强制杀死,那么这两个命令也能保证被杀死?
简单的方法&
行不通,因为如果我这样做
sh -c 'sleep 6 & sleep 3'
那么即使被杀,第一个sleep
也会继续徘徊。sh
答案1
@lesmana 的解决方案,使用 trap 是传统方法,但如前所述,无法处理这种kill -9
情况。
还有一种替代方法,设置一个进程来监视主进程,并在主进程退出时发出终止命令。进行监控的一个简单方法是建立一个到监视器的管道,当主进程退出时,内核将关闭监视器可以检测到的管道。
这是一个例子
#!/bin/bash
# show monitoring main process - Icarus Sparry
# [email protected]
# Handler function. Reads from stdin. If it doesn't read the word clean
# then send SIGINT to the process group.
handler(){
read
[ "$REPLY" = "clean" ] || kill -INT -$$
}
# invoke handler as a coprocess.
coproc handler
# some work in the background, wait for 20 seconds and print a message
{ sleep 20 ; echo bye 20 ; } &
# some work in the foreground
sleep 5 ; echo bye 5
# At this point tell the coprocess it was a clean end, so don't
# terminate the background
echo clean >&"${COPROC[1]}"
运行此命令将在 5 秒后输出,bye 5
15 秒后输出bye 20
。终止进程将导致协进程终止后台睡眠。
如果希望在前台工作完成时终止后台处理,则省略 Final echo clean >&"${COPROC[1]}"
,并可以选择从处理程序中删除[ "$REPLY" = "clean" ] ||
,留下 read 和kill。
答案2
trap 'kill 0' EXIT
在主脚本中使用。这将在脚本退出时杀死所有孩子。不管脚本如何退出。除了kill -9
。稍后会详细介绍。
为了演示我创建了两个文件
$ cat killchildren
#! /bin/sh
trap 'echo killing all children; kill 0' EXIT # this is the important line
./sleepx 4 &
./sleepx 2
echo killchildren done
$ cat sleepx
#! /bin/sh
trap 'echo sleep$1 killed' EXIT # just print that it was killed
sleep $1
trap - EXIT # clear trap so not print that it was killed
echo sleep$1 done
在这里它只是运行并保持不变
$ ./killchildren
sleep2 done
killchildren done
killing all children
sleep4 killed
在这里它被正常杀死kill
(注意我提高了睡眠时间,因为我打字速度不快)
$ ./killchildren &
[1] 13248
$ kill 13248
killing all children
sleep8 killed
sleep10 killed
[1]+ Terminated ./killchildren
在这里它被杀死了kill -9
$ ./killchildren &
[1] 13259
$ kill -9 13259
[1]+ Killed ./killchildren
$ # ... time passes ...
sleep8 done
sleep10 done
请注意,主脚本没有退出消息,孩子们也没有被杀死。
没有经过太多测试。截至 2018 年,至少可以在 arch linux 上与 sh 配合使用。
如果主脚本是 ,它将不起作用kill -9
。因为 的语义kill -9
是立即终止而不让进程执行任何操作。甚至没有陷阱处理。
也就是说,无论什么杀死你的进程都不应该用kill -9
.我认为这是一个错误。以下是有关为什么不这样做的更多信息kill -9
: