
Ich möchte ein Shell-Skript ausführen, das eine Schleife enthält und ewig laufen kann, was ich nicht möchte. Daher muss ich ein Timeout für das gesamte Skript einführen.
Wie kann ich unter SuSE ein Timeout für das gesamte Shellskript einführen?
Antwort1
Wenn GNU timeout
nicht verfügbar ist, können Sie verwenden expect
(Mac OS X, BSD usw. verfügen normalerweise nicht standardmäßig über GNU-Tools und -Dienstprogramme).
################################################################################
# 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
}
Bearbeiten Beispiel:
timeout 10 "ls ${HOME}"
Antwort2
Danke für die Abklärung.
Am einfachsten erreichen Sie Ihr Ziel, indem Sie Ihr Skript mit der Schleife innerhalb eines Wrappers ausführen, beispielsweise mit dem timeout
Befehl aus dem GNU Coreutils-Paket.
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'
Letztendlich wird es viel einfacher sein, als eine eigene Timeout-Funktion zu schreiben, die in Shells normalerweise nicht integriert ist.
Antwort3
Starten Sie einen Watchdog-Prozess aus Ihrem Skript heraus, um den übergeordneten Prozess zu beenden, wenn dieser zu lange läuft. Beispiel:
# watchdog process
mainpid=$$
(sleep 5; kill $mainpid) &
watchdogpid=$!
# rest of script
while :
do
...stuff...
done
kill $watchdogpid
Dieses Skript wird vom Watchdog nach fünf Sekunden beendet.
Antwort4
Es gibt auchcratimeout
von Martin Cracauer.
# 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'