Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to run a shell script that got a loop in it and it can go for ever which I do not want to happen. So I need to introduce a timeout for the whole script.

How can I introduce a timeout for the whole shell script under SuSE?

share|improve this question
4  
This is a very vague question. Can you please elaborate on what kind of timeout? Do you want a timeout on the whole script, or a timeout on a single function or command? What are you trying to do? –  Tim Kennedy Jul 18 '12 at 3:58
    
@TimKennedy: hope it's better now. –  Radek Jul 18 '12 at 4:04
1  
See also Timing out in a shell script (I don't consider it a duplicate because of my portability requirement which excludes tools such as timeout or expect) –  Gilles Jul 18 '12 at 23:37

4 Answers 4

up vote 12 down vote accepted

If GNU timeout is not available you can use expect (Mac OS X, BSD, ... do not usually have GNU tools and utilities by default).

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

    time=$1

    # start the command in a subshell to avoid problem with pipes
    # (spawn accepts one command)
    command="/bin/sh -c \"$2\""

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

    if [ $? = 1 ] ; then
        echo "Timeout after ${time} seconds"
    fi

}

Edit Example:

timeout 10 "ls ${HOME}"
share|improve this answer
    
Looks good. How can I see the output of the command executed on the screen? –  Radek Jul 18 '12 at 5:47
    
Hi, the output should be visible since stdout is not redirected anywhere. I added an example for the usage. In my case it prints the content of my home dir as expected. Which command is not printing any output? –  Matteo Jul 18 '12 at 5:53
    
I didn't call it properly. It works just great! Thank you. Only it doesn't output number of sec after timeout. –  Radek Jul 18 '12 at 7:00
    
@Radek Sorry, fixed –  Matteo Jul 18 '12 at 9:29
    
I'd like to highlight that if using GNU timeout, the return status of timeout itself is 124 in the case of a timeout, otherwise it's the command's return status (this is mentioned in Tim Kennedy's answer). –  QuasarDonkey Aug 11 '13 at 2:25

Thank you for the clarification.

The easiest way to accomplish what you're after is to run your script with the loop within a wrapper like the timeout command from the GNU Coreutils package.

root@coraid-sp:~# timeout --help            
Usage: timeout [OPTION] DURATION COMMAND [ARG]...
   or: timeout [OPTION]
Start COMMAND, and kill it if still running after DURATION.

Mandatory arguments to long options are mandatory for short options too.
  -k, --kill-after=DURATION
                   also send a KILL signal if COMMAND is still running
                   this long after the initial signal was sent.
  -s, --signal=SIGNAL
                   specify the signal to be sent on timeout.
                   SIGNAL may be a name like 'HUP' or a number.
                   See `kill -l` for a list of signals
      --help     display this help and exit
      --version  output version information and exit

DURATION is an integer with an optional suffix:
`s' for seconds(the default), `m' for minutes, `h' for hours or `d' for days.

If the command times out, then exit with status 124.  Otherwise, exit
with the status of COMMAND.  If no signal is specified, send the TERM
signal upon timeout.  The TERM signal kills any process that does not
block or catch that signal.  For other processes, it may be necessary to
use the KILL (9) signal, since this signal cannot be caught.

Report timeout bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
For complete documentation, run: info coreutils 'timeout invocation'

In the end, it will be much easier than writing your own timeout function, which shells tend to not have builtin.

share|improve this answer

There's also cratimeout by Martin Cracauer.

# cf. http://www.cons.org/cracauer/software.html
# usage: cratimeout timeout_in_msec cmd args
cratimeout 5000 sleep 600
cratimeout 5000 tail -f /dev/null
cratimeout 5000 sh -c 'while sleep 1; do date; done'
share|improve this answer

Launch a watchdog process from within your script to kill off its parent if it runs too long. Example:

# watchdog process
mainpid=$$
(sleep 5; kill $mainpid) &
watchdogpid=$!

# rest of script
while :
do
   ...stuff...
done
kill $watchdogpid

This script will be terminated by the watchdog after five seconds.

share|improve this answer
3  
But you will have to wait for the timeout every time. In your example your script will always run 5 seconds even if the script is much shorter. You should also store the PID of the watchdog and kill it at the end. –  Matteo Jul 18 '12 at 5:17
    
@Matteo Fair enough. Added. –  Kyle Jones Jul 18 '12 at 6:23
1  
Note that it may be more complicated than that, depending on what the ...stuff... is doing. See Timing out in a shell script –  Gilles Jul 18 '12 at 23:39

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.