これを行うと思った設定を思い出しましたが、うまくいきません。
#!/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 $?
答え2
動作するバージョンを見つけてください:
#!/bin/bash
export retval=
##At this time pid should hold the process id of myprog
{
##This is the subshell that launched and monitoring myprog
subsh=$!
##Since myprog is probably the only child process of this subsh, it should be pretty safe
pid=$(ps -f --ppid ${subsh} | grep -E "\bmyprog\b" | gawk '{print $2}' )
##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< <( myprog >>logfile 2>&1; echo $? )
echo "retval=$retval"
唯一の迷惑なのは、セマフォを使用してmyprogを終了するとプロセスの交換が中断され、エラーが発生するのに簡単につながる可能性があることです。