====== Timeout en SHELL ====== **timeout.sh** #!/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 # Make more portable by using the 'CHLD' # signal spec rather than 17. # V1.3, Oct 29 2009, Ján Sáreník # 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 # 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 ./timeout.sh 2 sleep 4 Un autre script s'appuyant sur timeout.sh permettant de lancer des processus à la volée avec des timeout : #!/bin/bash dir_result="/root/results" declare -a command command_pid usage() { echo "Usage : $0 , ," exit 1 } kill_proc() { for pid in ${command_pid[*]}; do [ -d /proc/$pid ] && [ `grep $0 /proc/${pid}/cmdline | wc -l` -ne 0 ] && kill -9 $pid && echo -e "$pid tué" done } 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