4

プロセスを追跡するスクリプトがあり、そのプロセスが終了した場合は再生成されます。追跡スクリプトに sigterm (たとえば) を与えることによって、追跡スクリプトがプロセスを強制終了するように指示された場合、追跡スクリプトにもプロセスを強制終了させたいと考えています。つまり、追跡スクリプトを強制終了すると、追跡しているプロセスも強制終了し、再生成して終了する必要はありません。

いくつかの投稿をまとめて (たとえば、PID ファイルを使用しないなどのベスト プラクティスだと思います)、次のようになります。

#!/bin/bash

DESC="Foo Manager"
EXEC="python /myPath/bin/FooManager.pyc"

trap "BREAK=1;pkill -HUP -P $BASHPID;exit 0" SIGHUP SIGINT SIGTERM

until $EXEC
do
    echo "Server $DESC crashed with exit code $?.  Restarting..." >&2
    ((BREAK!=0)) && echo "Breaking" && exit 1
    sleep 1
done

したがって、このスクリプトを 1 つの xterm で実行するとします。そして、別の xterm で次のようなスクリプトを送信します。

kill -HUP <tracking_script_pid>  # Doesn't work.
kill -TERM <tracking_script_pid>  #Doesn't work.

トラッキング スクリプトが終了しません。コマンドラインから FooManager.pyc を実行すると、SIGHUP と SIGTERM で終了します。とにかく、ここで何が間違っている可能性がありますか?おそらくそれを行うにはまったく別の方法がありますか?

ありがとう。

4

1 に答える 1

3

マニュアルから:

Bash がコマンドの完了を待っているときに、トラップが設定されたシグナルを受信した場合、コマンドが完了するまでトラップは実行されません。Bash がビルトインを介して非同期コマンドを待機している場合wait、トラップが設定されているシグナルを受信すると、waitビルトインは 128 より大きい終了ステータスですぐに戻り、その直後にトラップが実行されます。

強調は私です。

したがって、あなたの場合、コマンドが実行されている間、Bash はコマンドが終了するまで待機してからトラップをトリガーします。

これを修正するには、プログラムをジョブとして実行し、それを待つ必要があります。プログラムが 128 より大きいリターン コードで終了しない場合は、次のコードを単純化できますが、私はこの仮定をしていません。

#!/bin/bash

desc="Foo Manager"
to_exec=( python "/myPath/bin/FooManager.pyc" )

trap 'trap_triggered=true' SIGHUP SIGINT SIGTERM

trap_triggered=false
while ! $trap_triggered; do
   "${to_exec[@]}" &
   job_pid=$!
   wait $job_pid
   job_ret=$?
   if [[ $job_ret = 0 ]]; then
      echo >&2 "Job ended gracefully with no errors... quitting..."
      break
   elif ! $trap_triggered; then
      echo >&2 "Server $desc crashed with exit code $job_ret. Restarting..."
   else
      printf >&2 "Received fatal signal... "
      if kill -0 $job_pid >&/dev/null; then
          printf >&2 "killing job $job_pid... "
          kill $job_pid
          wait $job_pid
      fi
      printf >&2 "quitting...\n"
   fi
done

ノート。

  1. 大文字は悪い習慣と見なされるため、小文字の変数名を使用しました。大文字は Bash の予約名または環境変数と競合する可能性があります。
  2. コマンドを格納するために文字列ではなく、配列を使用しました。文字列では、スペースなどの変な文字を引数として渡したい場合、多くの問題が発生します。適切に引用された配列があれば、問題はありません。(関数を使用する方が良いと主張する人もいます。)
于 2014-12-22T18:30:25.877 に答える