Outils pour utilisateurs

Outils du site


tuto:linux:script_timeout_en_shell

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
Dernière révisionLes deux révisions suivantes
tuto:linux:script_timeout_en_shell [2010/01/22 21:44] – créée roottuto:linux:script_timeout_en_shell [2013/03/12 22:12] root
Ligne 1: Ligne 1:
 ====== Timeout en SHELL ====== ====== Timeout en SHELL ======
  
 +**timeout.sh**
 +<code bash>
 +#!/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
 +
 +</code>
 +
 +  ./timeout.sh 2 sleep 4
 +
 +Un autre script s'appuyant sur timeout.sh permettant de lancer des processus à la volée avec des timeout :
 <code> <code>
 #!/bin/bash #!/bin/bash
-  + 
-timeout=$1 +dir_result="/root/results" 
-command=$2 + 
-shift 2 +declare -a command command_pid 
-  + 
-check_pid_name() { +usage() { 
-        command=$1 +        echo "Usage : $0 <command1>,<timeout> <command2>,<command3>" 
-        childpid=$2 +        exit 1
-        [ -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 +kill_proc() { 
-  +        for pid in ${command_pid[*]}; do 
-safe_run() { +                [ -d /proc/$pid ] && [ `grep $0 /proc/${pid}/cmdline | wc -l` -ne && kill -9 $pid && echo -e "$pid tué" 
-        command=$1 +        done
-        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"+
 } }
 +
 +while getopts :h OPTION
 +do
 +        case "$OPTION" in
 +             h)
 +                usage
 +                ;;
 +        esac
 +done
 +
 +
 +nb_arg=`echo "$@" | awk -F\, '{ print NF }'`
 +
 +[ ! -d $dir_result ] && mkdir -p "$dir_result"
 +
 +echo "Table des processus :"
 +
 +for ((i=1; i<=$nb_arg; i+=1))
 +do
 +        log=`expr $i - 1`
 +        cmd=`echo "$@" | awk -v nb=$i -F\, '{ print $nb }' | sed s/^' '*//g`
 +
 +        command[${#command[*]}]=$cmd
 +
 +        if [ `echo "$cmd" | awk '{ print $1 }' | grep "^[[:digit:]]" | wc -l` -gt 0 ] ; then
 +                timeout=`echo "$cmd" | awk '{ print $1 }'`
 +        fi
 +
 +        if [ -z $timeout ] ; then
 +                (
 +                        $cmd 2>&1 1>$dir_result/$log
 +                        ret=$?
 +                        sleep 0.1
 +                        echo "$! : Fait ($ret)"
 +                        [ $ret -ne 0 ] && exit 1
 +                ) &
 +        else
 +                (
 +                        `dirname $0`/timeout.sh $cmd 2>&1 1>$dir_result/$log
 +                        ret=$?
 +                        sleep 0.1
 +                        if [ $ret -eq 0 ] ; then
 +                                echo "$! : Fait ($ret)"
 +                        else if [ $ret -eq 124 ] ; then
 +                                echo "$! : Timeout"
 +                                exit 1
 +                        else
 +                                echo  "$! : Fait($ret) !"
 +                                exit 1
 +                        fi
 +                        fi
 +                ) &
 +
 +                unset timeout
 +        fi
 +
 +        command_pid[${#command_pid[*]}]=$!
 +done
 +
 +for i in ${!command[*]}
 +do
 +        if [ `echo ${command[i]} | awk '{ print $1 }' | grep "^[[:digit:]]" | wc -l` -gt 0 ] ; then
 +                echo "${command_pid[i]} : `echo ${command[i]} | cut -d ' ' -f 2-` - timeout(`echo ${command[i]} | awk '{ print $1 }'`)"
 +        else
 +                echo "${command_pid[i]} : ${command[i]}"
 +        fi
 +done
 +
 +echo ""
 +
 +trap 'kill_proc' 2 3 15
 +
 +wait
 +
 +for i in ${!command[*]}
 +do
 +        [ -f "$dir_result/$i" ] && mv "$dir_result/$i" "$dir_result/${command_pid[i]}"
 +done
 </code> </code>
  
-  ./script 2 sleep 4+
tuto/linux/script_timeout_en_shell.txt · Dernière modification : 2013/03/12 22:13 de root