====== 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