腳本完成或被終止後終止子進程

腳本完成或被終止後終止子進程

假設我有一個如下所示的腳本

#!/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是唯一不起作用的訊號,因為腳本被無條件終止。

相關內容