すべての子プロセスが停止した場合にのみ、initスクリプトに「OK」を印刷させるにはどうすればよいですか?

すべての子プロセスが停止した場合にのみ、initスクリプトに「OK」を印刷させるにはどうすればよいですか?

私は非常に複雑なPythonアプリケーションを持っています。独自の初期化スクリプトがありますが、実行すると次のようになります。

sudo service my_service_daemon stop

「Stopping my_service_daemon [OK]」が印刷されますが、ジョブが完了するまで実際の子プロセスに残ります(信号15をキャプチャしますが、いくつかの操作を実行する必要があります)。したがって、子プロセスがまったくない場合にのみ「[OK]」メッセージを印刷したいと思います。これはinitスクリプトの一部です(CentOS 6で実行されています)。

...

. /etc/init.d/functions 

...

stop(){
    echo -n $"Stopping $prog: "
    if [ -a $pidfile ]; then
    group_id=$(ps -o pgid= $(cat $pidfile) | grep -o [0-9]*)
    if [ ! -z $group_id ]; then
            kill -- -$group_id
        success
    fi
    else
        failure
    fi
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && rm -f $lockfile $pidfile
}

答え1

プロセス処理を使用するsystemdか、cgroup子動物園を手動で制御します。出力ファイルps(1)とPIDファイルを操作すると、レースが簡単に発生する可能性があり、髪を引っ張って早期ハゲを引き起こすことが知られています。

答え2

完了したら、kill -- -$group_idすべてのプロセスが終了するまで待ちます。たとえば、私は次のことをします。

...
if [ ! -z "$group_id" ]; then
    kill -- -$group_id
    while pgrep -g $group_id &>/dev/null; do
        sleep 1
    done
    success
...

これにより、プロセスグループ()のすべてのメンバーがpgrep検索されます。通常、これらすべてのPIDを画面に印刷しますが、私たちはそれを見たくないので、すべての出力にリダイレクトしました。検索基準に一致するプロセスが1つ以上見つかった場合、正常に終了します()。サイクルを維持し続けます。プロセスが見つからない場合は「false」()で終了し、ループを終了してその行に到達します。堅いループのためにシステムが破壊されないようにシステムを挿入しました。-g$group_id/dev/nullpgrep0while1successsleep 1

答え3

Pythonアプリケーションでファイルを開いたままにします。つまり、実行プログラムスクリプトでそれをオンにし、アプリケーションでオフにしないでください。

このファイルはPIDファイルです。概念証明(並行性を扱わない):

pidfile=/var/run/myapp.pid
logfile=/var/log/myapp.log
start () {
  sh -c 'echo $$ >"$1"; exec myapp <"$1" >/dev/null 2>"$2"' &
}
stop () {
  master_pid=$(cat "$pidfile")
  while
    case " $(fuser "$pidfile" 2>/dev/null) " in
      *" $master_pid "*)
        echo "Master process is alive, killing it"
        kill "$master_pid";;
      "  ") echo "Master process is dead and no subprocesses remain"; false;;
      *) echo "Master process is already dead but some processes remain";;
    esac
  do
    sleep 1
  done
  rm "$pidfile"
}

関連情報