
ループを含むシェル スクリプトを実行したいのですが、永遠に実行されてしまう可能性があります。これは望ましくありません。そのため、スクリプト全体にタイムアウトを導入する必要があります。
SuSE でシェル スクリプト全体にタイムアウトを導入するにはどうすればよいですか?
答え1
GNU がtimeout
利用できない場合はexpect
、(Mac OS X、BSD などには通常、デフォルトで GNU ツールとユーティリティがありません) を使用できます。
################################################################################
# Executes command with a timeout
# Params:
# $1 timeout in seconds
# $2 command
# Returns 1 if timed out 0 otherwise
timeout() {
time=$1
# start the command in a subshell to avoid problem with pipes
# (spawn accepts one command)
command="/bin/sh -c \"$2\""
expect -c "set echo \"-noecho\"; set timeout $time; spawn -noecho $command; expect timeout { exit 1 } eof { exit 0 }"
if [ $? = 1 ] ; then
echo "Timeout after ${time} seconds"
fi
}
編集 例:
timeout 10 "ls ${HOME}"
答え2
ご説明ありがとうございます。
目的を達成する最も簡単な方法は、timeout
GNU Coreutils パッケージのコマンドのように、ラッパー内でループを使用してスクリプトを実行することです。
root@coraid-sp:~# timeout --help
Usage: timeout [OPTION] DURATION COMMAND [ARG]...
or: timeout [OPTION]
Start COMMAND, and kill it if still running after DURATION.
Mandatory arguments to long options are mandatory for short options too.
-k, --kill-after=DURATION
also send a KILL signal if COMMAND is still running
this long after the initial signal was sent.
-s, --signal=SIGNAL
specify the signal to be sent on timeout.
SIGNAL may be a name like 'HUP' or a number.
See `kill -l` for a list of signals
--help display this help and exit
--version output version information and exit
DURATION is an integer with an optional suffix:
`s' for seconds(the default), `m' for minutes, `h' for hours or `d' for days.
If the command times out, then exit with status 124. Otherwise, exit
with the status of COMMAND. If no signal is specified, send the TERM
signal upon timeout. The TERM signal kills any process that does not
block or catch that signal. For other processes, it may be necessary to
use the KILL (9) signal, since this signal cannot be caught.
Report timeout bugs to [email protected]
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
For complete documentation, run: info coreutils 'timeout invocation'
最終的には、シェルに組み込まれていないことが多い独自のタイムアウト関数を作成するよりもはるかに簡単になります。
答え3
スクリプト内からウォッチドッグ プロセスを起動し、実行時間が長すぎる場合に親を強制終了します。例:
# watchdog process
mainpid=$$
(sleep 5; kill $mainpid) &
watchdogpid=$!
# rest of script
while :
do
...stuff...
done
kill $watchdogpid
このスクリプトは 5 秒後にウォッチドッグによって終了します。
答え4
また、cratimeout
マーティン・クラカウアー著。
# cf. http://www.cons.org/cracauer/software.html
# usage: cratimeout timeout_in_msec cmd args
cratimeout 5000 sleep 600
cratimeout 5000 tail -f /dev/null
cratimeout 5000 sh -c 'while sleep 1; do date; done'