次のスクリプトがあるとしましょう。
#!/usr/bin/env zsh
./subscript.sh &
# do stuff
...
# do more stuff
次の場合、実行中のプロセスsubscript.sh
(およびそれによって開始されたすべてのプロセス)が完全に終了したいと思います。
- 上記のスクリプトが終了します。
- 上記のスクリプトは何らかの理由で終了します。
上記をどのように実施しますか?これはシェルによって自動的に処理されますか?
答え1
シェルは子プロセスを自発的に終了しません。結局のところ、バックグラウンドジョブはバックグラウンドで実行する必要があり、親プロセスの寿命には気にしません。 (場合によっては、対話型シェルが終了すると子プロセスを終了します。これは常に望ましいとは限りません。nohup
.)
シェルスクリプトがトラップ可能なシグナルによって終了または終了したときにバックグラウンドジョブを終了させることができます。ジョブのプロセスIDを記録し、トラップで終了します。これはサブジョブではなくジョブのみを終了します(元のプロセスがバックグラウンドで開始されたため)。
jobs=()
trap '((#jobs == 0)) || kill $jobs' EXIT HUP TERM INT
…
subscript1 & jobs+=($!)
subscript2 & jobs+=($!)
…
すべてのプロセスとそのサブプロセスを終了させるには、追加の計画が必要です。 1つのアプローチは、すべてのプロセスが一意のファイルを開くように配置することです。すべてのプロセスを終了するには、ファイルが開いているすべてのプロセスを終了します。子プロセスはファイルを閉じてエスケープできます。
#!/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
スクリプトが無条件に終了するため、機能しない唯一のシグナルです。