假设我有一个如下所示的脚本
#!/usr/bin/env zsh
./subscript.sh &
# do stuff
...
# do more stuff
我希望运行的进程subscript.sh
(以及由它启动的任何进程)在以下情况下完全终止:
- 上面的脚本退出
- 上面的脚本因任何原因被终止。
我如何执行上述规定?这是由 shell 自动处理的吗?
答案1
shell 绝对不会自发地终止其子进程 - 毕竟后台作业应该在后台运行并且不关心其父进程的生命。 (在某些情况下,交互式 shell 会在退出时杀死其子进程——这并不总是可取的,因此nohup
.)
您可以让 shell 脚本在退出或被可捕获信号终止时终止其后台作业。记录作业的进程 ID,并从陷阱中杀死它们。请注意,这只会杀死作业(如在后台启动的原始进程),而不是其子进程。
jobs=()
trap '((#jobs == 0)) || kill $jobs' EXIT HUP TERM INT
…
subscript1 & jobs+=($!)
subscript2 & jobs+=($!)
…
如果您想确保终止所有进程及其子进程,则需要进行更多规划。一种方法是安排所有进程打开一个唯一的文件。要杀死所有进程,请杀死所有打开该文件的进程。子进程可以通过关闭文件来逃脱。
#!/bin/sh
lock_file=$(mktemp)
exec 3<"$lock_file"
your_script
status=$?
exec 3<&-
fuser -k "$lock_file"
exit $status
答案2
您可以捕获 EXIT 并向脚本的进程组发送信号。
在Linux上
trap 'kill -SIGTERM 0' EXIT
在 FreeBSD 上
trap 'kill -15 -$$' EXIT
SIGKILL
是唯一不起作用的信号,因为脚本被无条件杀死。