脚本完成或被终止后终止子进程

脚本完成或被终止后终止子进程

假设我有一个如下所示的脚本

#!/usr/bin/env zsh
./subscript.sh &
# do stuff
...
# do more stuff

我希望运行的进程subscript.sh(以及由它启动的任何进程)在以下情况下完全终止:

  1. 上面的脚本退出
  2. 上面的脚本因任何原因被终止。

我如何执行上述规定?这是由 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是唯一不起作用的信号,因为脚本被无条件杀死。

相关内容