スクリプトが終了した後または強制終了した後にサブプロセスを強制終了する

スクリプトが終了した後または強制終了した後にサブプロセスを強制終了する

次のようなスクリプトがあるとします

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

subscript.sh実行中のプロセス(およびそれによって開始されたすべてのプロセス) を、次の場合に完全に終了したいと思います。

  1. 上記のスクリプトは終了する
  2. 上記のスクリプトは何らかの理由で強制終了されます。

上記をどのように強制できますか? これはシェルによって自動的に処理されますか?

答え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スクリプトが無条件に強制終了されるため、これが機能しない唯一のシグナルです。

関連情報