Outils pour utilisateurs

Outils du site


tuto:linux:script_timeout_en_shell

Ceci est une ancienne révision du document !


Timeout en SHELL

#!/bin/sh

# Execute a command with a timeout

# Author:
#    http://www.pixelbeat.org/
# Notes:
#    If the timeout occurs the exit status is 124.
#    There is an asynchronous (and buggy) equivalent of this
#    script packaged with bash (under /usr/share/doc/ in my distro),
#    which I only noticed after writing this.
#    Note there is a timeout command packaged with coreutils since v7.0
#    I noticed later again that there is a C equivalent of this packaged
#    with satan by Wietse Venema, and copied to forensics by Dan Farmer.
# Changes:
#    V1.0, Nov  3 2006, Initial release
#    V1.1, Nov 20 2007, Brad Greenlee <brad@footle.org>
#                       Make more portable by using the 'CHLD'
#                       signal spec rather than 17.
#    V1.3, Oct 29 2009, Ján Sáreník <jasan@x31.com>
#                       Even though this runs under dash,ksh etc.
#                       it doesn't actually timeout. So enforce bash for now.
#                       Also change exit on timeout from 128 to 124
#                       to match coreutils.
#    V2.0, Oct 30 2009, Ján Sáreník <jasan@x31.com>
#                       Rewritten to cover compatibility with other
#                       Bourne shell implementations (pdksh, dash)

if [ "$#" -lt "2" ]; then
    echo "Usage:   `basename $0` timeout_in_seconds command" >&2
    echo "Example: `basename $0` 2 sleep 3 || echo timeout" >&2
    exit 1
fi

cleanup()
{
    trap - ALRM               #reset handler to default
    kill -ALRM $a 2>/dev/null #stop timer subshell if running
    kill $! 2>/dev/null &&    #kill last job
      exit 124                #exit with 124 if it was running
}

watchit()
{
    trap "cleanup" ALRM
    sleep $1& wait
    kill -ALRM $$
}

watchit $1& a=$!                      #start the timeout
shift                                 #first param was timeout for sleep
trap "cleanup" ALRM INT               #cleanup after timeout
("$@" || exit $?)& wait $!; RET=$?    #start the job wait for it and save its return value
kill -ALRM $a                         #send ALRM signal to watchit
wait $a                               #wait for watchit to finish cleanup
exit $RET                             #return the value

Un autre un peu moins optimisé :

#!/bin/bash
 
timeout=$1
command=$2
shift 2
 
check_pid_name() {
        command=$1
        childpid=$2
        [ -d /proc/$childpid ] || return 1
        [ $(grep -c $command /proc/$childpid/cmdline 2>/dev/null) -gt 0 ] && return 0 || return 1
}
 
[ -z "$command" ] && echo "Usage: safecmd   [args]">&2 && exit 1
 
safe_run() {
        command=$1
        shift
        $command $*
        kill $$
}
 
safe_run $command $* &
childpid=$!
sleep $timeout
 
check_pid_name $command $childpid && {
        kill $childpid
        sleep 0.1
        check_pid_name $command $childpid && kill -9 $childpid
        echo "$command $* timed out"
}
./script 2 sleep 4
tuto/linux/script_timeout_en_shell.1264355592.txt.gz · Dernière modification : 2010/01/24 17:53 de root