シェル関数でタイムアウト

うーん,と新しいアルゴリズムを考えて,とりあえず,プロトタイプ実装する,ということを,ときどきします.その後は,たいてい,パラメータをいろいろ変えてみて,データを取得するのですが,プロトタイプなので,よく異常終了したり,もっと悪い場合は無限ループに入るのか,だんまりになったりします.週末にデータを取ろうと思っても,起動して数パターンのデータを取得したところでスタックして,そのまま週末のほとんどをムダにする,なんてことがよくあります.

そこで,一定時間内に応答が返ってこなかったら,強制終了するタイムアウト機能がほしい!ということで,そんなシェルスクリプト・コマンドはいくらでもあるだろう,と思っていたのですが,ほとんど見つかりません.

なので,自作してみました.使い方は,timeout 5 sleep 10とかすると,10秒スリープしようとするのですが,約5秒でタイムアウトして,プロセスがKILLされます.echo文は動作確認用なので,実際に利用する場合は,適当に削除してください.

timeout()
{
    count_timeout=$1
    shift 1;
    echo 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 $pid is alive.
	    count=`expr $count + 1`
	    sleep 1
	else
	    echo $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 $pid was terminated by a SIG$(kill -l $?) signal.
    fi
}


timeout 5 sleep 3
timeout 5 sleep 10

これでよし,と思ったら,netatalkのパッケージにtimeoutという,そのものズバリのコマンドが含まれているようです...

まぁ,netatalkのパッケージがどこにでもインストールされているわけではないし,timeoutのためだけに,netatalkをインストールするのも問題がある(かもしれない)ので,それなりに利用価値は残っていることにしておきます.