1753511 Members
5333 Online
108795 Solutions
New Discussion юеВ

Re: Shell script timeout

 
SOLVED
Go to solution
Patrick Ware_1
Super Advisor

Shell script timeout

Hello all,

I have a script that sometimes has the tenancy to hang on certain servers. The script has two functions that it executes. Is there anyway to make it so that the script or functions in the script timeout after a certain time limit is reached?

Thanks in advance!
9 REPLIES 9
Manix
Honored Contributor

Re: Shell script timeout

Hello Patrick,

What functions you are calling ,we have "-m"
time out switch for ping.

http://h30499.www3.hp.com/t5/General/how-to-set-timeout-in-shell-script/m-p/3351662#M99224


Thanks
Manix

HP-UX been always lovable - Mani Kalra
Patrick Ware_1
Super Advisor

Re: Shell script timeout

Custom functions.
Steven Schweda
Honored Contributor

Re: Shell script timeout

When you did a Forum search for keywords
like, say,
shell script timeout
did you find nothing which might be useful?


http://h30499.www3.hp.com/t5/Languages-and-Scripting/how-to-set-time-outs-for-commands-in-a-script/m-p/5041233#M36021

James R. Ferguson
Acclaimed Contributor
Solution

Re: Shell script timeout

Hi Patrick:

One way would be to fork() a process to monitor a part of itself. In a pure shell script we can emulate that by running a piece (a function or subroutine) in the background.

Here's a working example of what I mean:

# cat ./monitor
#!/bin/sh
typeset MAXSEC=10
typeset TIME_0=${SECONDS}
function do_work
{
while true
do
date
[ ! -z "$1" ] && break #...to fake a fast execution...
sleep 1 #...emulates work...
done
echo "...finished..."
}
do_work $1 &
WORKER=$!
while [ "$((${SECONDS}-${TIME_0}))" -le "${MAXSEC}" ]
do
sleep 1 #...don't buzz processor needlessly...
kill -0 ${WORKER} 2>/dev/null
[ $? -ne 0 ] && exit 0
done
echo "Time Limit exceeded"
kill ${WORKER} 2>/dev/null
exit 1

...to see how this works, run the script two ways:

# ./monitor quick

...and:

# ./monitor

Regards!

...JRF...
Patrick Ware_1
Super Advisor

Re: Shell script timeout

Maybe I used the wrong key words.
Patrick Ware_1
Super Advisor

Re: Shell script timeout

I never thought of doing it that way, and I appreciate the help! The only issue I am running into is the fact that I have two, so after the first one, the script is exiting. I'm trying to figure out a way for that not to happen, but haven't gotten there yet.
Patrick Ware_1
Super Advisor

Re: Shell script timeout

I may have just figured it out. If I call the second function from the first, it seems to work. Any drawbacks to this?
James R. Ferguson
Acclaimed Contributor

Re: Shell script timeout

Hi (again) Patrick:

> The only issue I am running into is the fact that I have two, so after the first one, the script is exiting.

Then consider doing something like this variation:

# cat ./monitor
#!/usr/bin/sh
typeset MAXSEC=10
function do_work
{
typeset CMD=$1
typeset ONE=$2

while true
do
eval "$1"
[ ! -z "${ONE}" ] && break #...to fake a fast execution...
sleep 1 #...emulates work...
done
echo "...finished..."
}
function monitor
{
typeset WORKER=$!
typeset TIME_0=${SECONDS}
while [ "$((${SECONDS}-${TIME_0}))" -le "${MAXSEC}" ]
do
sleep 1 #...don't buzz processor needlessly...
kill -0 ${WORKER} 2>/dev/null
[ $? -ne 0 ] && return 0
done
echo "Time Limit exceeded"
kill ${WORKER} 2>/dev/null
return 1
}
do_work "date" $1 &
monitor && echo "rc=$?" || echo "rc=$?"
do_work "uname -a" $1 &
monitor && echo "rc=$?" || echo "rc=$?"
exit 0
#_end_

...This is easily amended to pass the MAXSEC value as an argument to allow different processes to be bounded by different time limits.

Regards!

...JRF...
James R. Ferguson
Acclaimed Contributor

Re: Shell script timeout

Hi Patrick:

Depending on the nature of your processes, and whether or not you care about partial output, you could wrap your script with a small Perl wrapper and leverage Perl's signal handling abilities.

Consider a ahell script called "watch.sh:

# cat ./watch.sh
#!/usr/bin/sh
X=0
for N in 1 2 3 4 5
do
date
sleep 1
done
echo "...finished!"

...Now create a wrapper thusly:

# cat ./watch.pl
#!/usr/bin/perl
use strict;
use warnings;
my $command=shift or die "Command or script expected\n";
my $timeout=shift || 3;
$SIG{ALRM}=sub{die "Timeout!\n"};
alarm $timeout;
my @results=`$command`;
print @results;
1;

...The wrapper expects to be passed the name of the process to be executed as it's first argument. An optional second argument defines the timeout. This value defaults to 3-seconds in the above variation. To see the script in action, try:

# ./watch.pl ./watch.sh

...versus:

# ./watch.pl ./watch.sh 10

Regards!

...JRF...