第一種
function timeout() {
waitsec=$SLEEP_TIME
( $* ) & pid=$!
( sleep $waitsec && kill -HUP $pid ) 2>/dev/null & watchdog=$!
# if command finished
if wait $pid 2>/dev/null; then
pkill -HUP -P $watchdog
wait $watchdog
fi
# else: command interrupted
}
第二種
function timeout()
{
local time cmd pid
if echo "$1" | grep -Eq '^[0-9]+'; then
time=$1
shift && cmd="$@"
else
time=5
cmd="$@"
fi
$cmd &
pid=$!
while kill -0 $pid &>/dev/null; do
sleep 1
let time-=1
if [ "$time" = "0" ]; then
kill -9 $pid &>/dev/null
wait $pid &>/dev/null
fi
done
}
假設有一個測試腳本sleep.sh:
$ cat sleep.sh
echo "sleep $1 seconds"
sleep $1
echo "awake from sleep"
現在利用我們寫的timeout函數來達到超時kill功能:
$ time sh timeout.sh 2 'sh sleep.sh 100'
sleep 100 seconds
real 0m2.005s
user 0m0.002s
sys 0m0.001s
看最終執行的時間,差不多就是2秒鍾。
上面timeout函數實現的代碼中,利用了兩個技巧:
- kill -0 $pid:發送信號0給進程,可以檢查進程是否存活,如果進程不存在或者沒有權限,則返回錯誤,錯誤碼為1;
- wait $pid &>/dev/null:等待某個進程退出返回,這樣相對比較優雅,同時將錯誤重定向到黑洞,從而隱藏后台進程被kill的錯誤輸出;
