read

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 4

which will output

./safecmd.1: line 34: 11739 Terminated               safe_run $command $*
sleep 4 timed out
or ./safecmd 2 sleep 1

which will output

Terminated

Indicating 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.

Blog Logo

Fernando Ipar


Published

Image

Fernando Ipar

"Tell my wife I love her very much, she knows"

Back to Overview