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
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
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]
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
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