Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Code review: timeout in a shell script

598 views
Skip to first unread message

Teo

unread,
Mar 31, 2009, 2:43:28 AM3/31/09
to
Hi,

I need to timeout commands in a shell script and by looking a several
hints I came up with:

################################################################################
# Executes command with a timeout
# Params:
# $1 timeout in seconds
# $2 command
# Returns 1 if timed out 0 otherwise
timeout() {

time=$1
command=$2

# start command
$command &
PID=$!

if [ "${PID}" = "0" ] ; then
# command not executed
return 0;
fi

# start killer process
( sleep "${time}"; kill "${PID}"; ) &
KILLER=$!

# wait for process to finish
wait ${PID} 2>/dev/null

# process finished
if kill -0 ${KILLER} 2>/dev/null ; then
# killer still running: kill it
# with SIGINT (no 'Terminated' message is printed)
kill SIGINT "${KILLER}" 2>/dev/null
return 0
else
# killer not running (command was killed by the killer)
return 1
fi

}

It seems to work but I would appreciate comments on its portability.

Many thanks

Matteo

Kenny McCormack

unread,
Mar 31, 2009, 7:21:27 AM3/31/09
to
In article <aa9e017f-3bfe-4197...@c36g2000yqn.googlegroups.com>,

Teo <matteo...@gmail.com> wrote:
>Hi,
>
>I need to timeout commands in a shell script and by looking a several
>hints I came up with:
...

>It seems to work but I would appreciate comments on its portability.

It is a lot easier and more robust just to use Expect.

Teo

unread,
Mar 31, 2009, 8:05:46 AM3/31/09
to
On Mar 31, 1:21 pm, gaze...@shell.xmission.com (Kenny McCormack)
wrote:
> In article <aa9e017f-3bfe-4197-8f6a-add3b4a4f...@c36g2000yqn.googlegroups.com>,

>
> Teo  <matteo.co...@gmail.com> wrote:
> >Hi,
>
> >I need to timeout commands in a shell script and by looking a several
> >hints I came up with:
> ...
> >It seems to work but I would appreciate comments on its portability.
>
> It is a lot easier and more robust just to use Expect.

Hi,

I did not think about it but it could be a possibility. I never used
expect so tell me if I am wrong.

I am trying with:

timedexec () {

time=$1
command=$2

expect -c "set timeout $time; spawn $command; expect timeout
{ exit 1 } eof { exit 0 }"

if [ $? = 1 ] ; then
echo "$2 timed out after $1 seconds"
else
echo "$2 finished before timeout ($1 seconds)"
fi

}

which works fine. I now have following problems:

* how can I make expect not to print "spawn whatever"?
* how can I make it work with piped commands?
something like
spawn ls | wc -l

Many thanks

Matteo

Kenny McCormack

unread,
Mar 31, 2009, 8:35:24 AM3/31/09
to
In article <75b53d4d-86bf-430a...@3g2000yqk.googlegroups.com>,
Teo <matteo...@gmail.com> wrote:
...

>I am trying with:
>
>timedexec () {
>
> time=$1
> command=$2
>
> expect -c "set timeout $time; spawn $command; expect timeout
>{ exit 1 } eof { exit 0 }"
>
> if [ $? = 1 ] ; then
> echo "$2 timed out after $1 seconds"
> else
> echo "$2 finished before timeout ($1 seconds)"
> fi
>
>}
>
>which works fine. I now have following problems:
>
>* how can I make expect not to print "spawn whatever"?
>* how can I make it work with piped commands?
> something like
> spawn ls | wc -l

Good! It looks like you understand the tool and how it can be used to
address this problem. From here on, it is basically just a matter of
refining it. I suggest you continue with what you have until it does
everything you want it to do.

For reference, here is my "maxtime" script. Note that I have never
addressed the issue of piped commands, but the usual solution to that
is, of course, to run the command via: sh -c 'the|command;echo $foo;whatever'
You can probably work that into the script if needed.

#!/usr/bin/expect --
# Usage: maxtime [-q] <maxsecs> <cmd> [<arg(s)>]
set echo ""
if {[lindex $argv 0] == "-q"} {
set echo "-noecho"
set argv [lrange $argv 1 end]
}
set timeout [lindex $argv 0]
if [catch {eval spawn $echo [lrange $argv 1 end]}] {
puts "Usage: maxtime \[-q] <timeINsecs> <cmd> \[<arg(s)>]"
exit -1
}
if [catch {set exitval $env(MAXTIME_exitval)}] { set exitval -1 }
expect timeout { puts stderr "[lrange $argv 1 1]: Timeout" ; exit $exitval }
exit [lrange [wait] 3 3]

Teo

unread,
Mar 31, 2009, 11:36:06 AM3/31/09
to
Dear Kenny

On Mar 31, 2:35 pm, gaze...@shell.xmission.com (Kenny McCormack)
wrote:
> In article <75b53d4d-86bf-430a-b3cf-40db87e24...@3g2000yqk.googlegroups.com>,Teo  <matteo.co...@gmail.com> wrote:
[...]


> Good!  It looks like you understand the tool and how it can be used to
> address this problem.  From here on, it is basically just a matter of
> refining it.  I suggest you continue with what you have until it does
> everything you want it to do.

Yes indeed. I now wrap every command with sh -c and works perfectly
with pipes.

I think I'll take a closer look on expect for my next scripts :-)

Matteo

Glenn Jackman

unread,
Mar 31, 2009, 3:34:41 PM3/31/09
to
At 2009-03-31 08:05AM, "Teo" wrote:
>
> expect -c "set timeout $time; spawn $command; expect timeout
> { exit 1 } eof { exit 0 }"
[...]

> * how can I make expect not to print "spawn whatever"?

with the command: log_user 0

help with expect can be found also at comp.lang.tcl

--
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous

0 new messages