スクリプトが完了または終了したら、サブプロセスを終了します。

スクリプトが完了または終了したら、サブプロセスを終了します。

次のスクリプトがあるとしましょう。

#!/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スクリプトが無条件に終了するため、機能しない唯一のシグナルです。

関連情報