EDIT: This can be safely replaced by timeout
Sometimes, in a shell script, you need to run a command that might go on forever (or an amount of time long enough to be called forever) due to poor coding of the software and wrong external conditions (network down or overloaded, overloaded system, a changed private key, etc).
In order to avoid this situations, here's a small shell script that will execute any command with a guaranteed timeout:
#!/bin/bash timeout=$1 command=$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 "I need a command to run">&2 && exit 1 [ $# -eq 2 ] && shift || shift 2 $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" }
As you can see, it's quite simple. You just have to start the desired command in the background, sleep for the timeout, and then kill the process if it's still running.
Yes, this script has a defect, all the commands will wait $timeout to run, but that's easy to solve. I'll post an improved (but slightly more complex) version in my next post.