Timeout on shell command.

Liam R. E. Quin lee at sq.sq.com
Wed Aug 15 14:56:49 AEST 1990


brister at decwrl.dec.com (James Brister) writes:
>I'd like to have a shell script run a command, but if that command doesn't
>finish in X seconds, then the script should kill it, if the command
>finishes sooner then the script should immediately continue.

tchrist at convex.COM (Tom Christiansen) writes:
>Here's timeout.c; syntax is 'timeout seconds command'.  

That is probably the neatest solution.
Another way (if you need a shell-only solution) is

Process One:
    # write my PID ($$) to a tmp file, tmp1
	echo $$ > $tmp1
    # run command
	$command
    # mark ourselves as done:
	/bin/rm -f $tmp1
    # if tmp2 exists, kill that process
	test -f $tmp2 && kill `cat $tmp2`

Process Two:
    # write my PID to a file, tmp2
	echo $$ > $tmp2
    # wait a while
	sleep 27
    # mark ourselves as done so the other half does not kill us now
	/bin/rm -f $tmp2
    # kill the other half if it is still running
	test -f $tmp1 && kill `cat $tmp1`

Now do
    ProcessOne &
    ProcessTwo &
    wait

If you have other background tasks, write these three "lines" out to
a temporary file and execute that -- then the wait will only wait for
ProcessOne and ProcessTwo.

If you don't want the PIDs to appear when you do the Process1 &, you
can play tricks with
	/bin/sh -c "command &"
which won't print the PID of the background process on most systems, but
only works with simple commands (no |, &&, etc) without care.

The variant
	( /bin/sh -c "exec 2>&3; command" & ) 3>&2 2>/dev/null
works better.  It says, 
					     ^^^^
Run the thing in (  ) with file descriptor 3 open in addition to the
standard 0, 1 and 2  (2 is standard error, used for messages).  Make
file descriptor 3 be the same as descriptor 2.

Having done that, send everything written         ^^^^^^^^^^^
on file descriptor 2 (standard error) to /dev/null -- in other words,
throw away all error messages.  This will throw away the PID, which is
what we want, but will also throw away any error messages generated
by "command". 

The
	exec 2>&3;
tells the /bin/sh _inside_ the ( )  to make file descriptor 2 be the
same as file descriptor 3, which we previously opened as the original
standard error.  So this restores standard error messages for the
command inside the quotes.
Which is what we need.

Well, you might say that it would be less arcane to include the C
program `timeout' given by Tom Christiansen, and to compile it on the
fly, but in practice the commands are likely (I hope) to be simple, and
the first form with /bin/sh -c "command" will probably work fine.

Lee
-- 
Liam R. E. Quin,  lee at sq.com, {utai,utzoo}!sq!lee,  SoftQuad Inc., Toronto



More information about the Comp.unix.questions mailing list