シェル関数でタイムアウト その2
先日,シェルスクリプトでタイムアウト用の関数を作ってみたのですが,計測したアプリケーションは,デーモンのような挙動をするプロセスでした.先日のスクリプトでは,内部で起動したプロセスのpidを見ています.ですが,デーモンの場合,起動したら,子プロセスを作成して,親プロセスは,さっさと終了してしまいます.そのため,タイムアウト関数も監視対象のpidはいなくなっているので,正しく動作しなくなっていたのでした.
というわけで,だいぶadhocな実装になってしまいますが,対策として,pidではなくプロセス名で監視して,タイムアウト時にkillallで,そのプロセス名を持つプロセスを全滅させることにしました.おかげで副作用が強烈になったので,注意して使いましょう...
使い方は,前回は「timeout 5 sleep 10」でしたが,プロセス名対応版では,「timeout_name 5 sleep sleep 10」のように2番目の引数に,監視対象のプロセス名を入れてください.
#!/bin/sh timeout() { count_timeout=$1 shift 1; echo timeout: exec \'$@\' $@ & pid=$! count=0 while [ $count -lt $count_timeout ] do isalive=`ps -ef | grep $pid | grep -v grep | wc -l` if [ $isalive -eq 1 ]; then echo timeout: $pid is alive. count=`expr $count + 1` sleep 1 else echo timeout: $pid was disapeared. count=`expr $count_timeout` fi done isalive=`ps -ef | grep $pid | grep -v grep | wc -l` if [ $isalive = 1 ]; then kill -kill $pid wait $pid echo timeout: $pid was terminated by a SIG$(kill -l $?) signal. fi } timeout_name() { count_timeout=$1 pname=$2 shift 2; echo timeout: $pname exec \'$@\' $@ & count=0 while [ $count -lt $count_timeout ] do isalive=`ps -ef | grep $pname | grep -v grep | wc -l` if [ $isalive -ne 0 ]; then echo timeout: $pname is alive. count=`expr $count + 1` sleep 1 else echo timeout: $pname was disapeared. count=`expr $count_timeout` fi done isalive=`ps -ef | grep $pname | grep -v grep | wc -l` if [ $isalive -ne 0 ]; then killall -kill $pname echo timeout: $pname was terminated by a SIG$(kill -l $?) signal. fi }