EDIT: This can be safely replaced by timeout
Here's an improved version of the safecmd script. This one doesn't always wait for $timeout seconds even if the command you're running exits successfully. In that case, it kills the monitor script and ends at the proper time.
Here's the code:
#!/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" } </pre> You can try it how like this, for example:
./safecmd 2 sleep 4which will output
./safecmd.1: line 34: 11739 Terminated safe_run $command $* sleep 4 timed outor ./safecmd 2 sleep 1which will output
TerminatedIndicating that sleep 1 finished successfully
This is still missing something. You can't test for the success of the command you pass safecmd, if it exits successfully you'll see the same return code than if it would have exited with an error.
In order to improve this, as far as I can tell, you have to use two scripts, one just as the wrapper (to use one separate script instead of the function safe_run()). That's the way this is handled in Highbase, and I'll post a full example in my next post on this subject.