必要に応じてバックグラウンドプロセスを監視し、シャットダウン中にバックグラウンドプロセスから終了コードを取得する安定した方法

必要に応じてバックグラウンドプロセスを監視し、シャットダウン中にバックグラウンドプロセスから終了コードを取得する安定した方法

これを行うと思った設定を思い出しましたが、うまくいきません。

#!/bin/bash

echo "Launching a background process that may take hours to finish.."
myprog &
pid=$!
retval=
##At this time pid should hold the process id of myprog
echo "pid=${pid}"

{
    ##check if the process is still running
    psl=$(ps -f -p ${pid} | grep -E "\bmyprog\b")
    killit=
    while [[ ! -z ${psl} ]]
    do
        ##if a file named "kill_flag" is detected, kill the process
        if [[ -e "kill_flag" ]]
        then
            killit=YES
            break
        fi
        #check every 3 seconds
        sleep 3
        psl=$(ps -f -p ${pid} | grep -E "\bmyprog\b")
    done

    ##killit not set, normal exit, read from fd5
    if [[ -z ${killit} ]]
    then
        read <&5 retval
  else
    ##kill here, the wait will return and the sub process ends
    kill ${pid}
  fi

} 5< <( wait ${pid} > /dev/null 2>&1; echo $? )

echo "retval=$retval"

最初の実行では、すべてが大丈夫に見えます。プロセスを終了して終了できます。touch kill_flagそれ以外の場合は、myprogが正常に完了するのを待ちます。しかし、私はいつもretvalから-1を得ることがわかりました。 myprog は 0 を返します。これは通常の動作として確認されます。さらなる調査の結果、" echo $?"部分はwaitコマンドが終了した後ではなく、スクリプトが開始された直後に実行されたことがわかりました。私は何が起こっているのか知りたいです。私は初めてbashに触れました。

ベストアンサー1

wait現在のシェルプロセスの子プロセスでのみ機能できます。内部コードを解釈するサブシェルは、<(...)姉妹プロセスを待つことはできません。

待機は、pidを起動したのと同じシェルプロセスによって実行する必要があります。zsh代わりに使用してくださいbash。 (他のバックグラウンドジョブが実行されていないと仮定します。)

cmd & pid=$!
while (($#jobstates)) {
  [[ -e killfile ]] && kill $pid
  sleep 3
}
wait $pid; echo $?

おすすめ記事