4

Sometimes my bash scripts are hanging and hold without clear reason

So they actually can hang for ever ( script process will run until I kill it )

Is it possible to combine in the bash script time out mechanism in order to exit from the program after for example ½ hour?

maihabunash
  • 1,632
  • 9
  • 34
  • 60

2 Answers2

12

This Bash-only approach encapsulates all the timeout code inside your script by running a function as a background job to enforce the timeout:

#!/bin/bash

Timeout=1800 # 30 minutes

function timeout_monitor() {
   sleep "$Timeout"
   kill "$1"
}

# start the timeout monitor in 
# background and pass the PID:
timeout_monitor "$$" &
Timeout_monitor_pid=$!

# <your script here>

# kill timeout monitor when terminating:
kill "$Timeout_monitor_pid"

Note that the function will be executed in a separate process. Therefore the PID of the monitored process ($$) must be passed. I left out the usual parameter checking for the sake of brevity.

Michael Jaros
  • 4,586
  • 1
  • 22
  • 39
  • Will the background process not keep the main process running? Meaning this will ALWAYS timeout, even if the script has executed in full? – Alan Kavanagh Apr 25 '16 at 14:36
  • @Alan: Yes it will always timeout. No, the main process will not remain running, but the background process will. If that is a problem for you, you could store the background process' PID from `$!` and kill it before terminating the main program. Or use an `EXIT` handler. Or use Gnu's `timeout` as rici suggested. – Michael Jaros Apr 26 '16 at 07:15
  • Ya - Good answer. Storing the timeout_monitor PID and killing it should do the job. Might think of incorporating this into your answer, it's one of the first that pops up on google. (I'm logging whether or not the script times out, so I need the background process to die if the script executes in full beforehand) – Alan Kavanagh Apr 26 '16 at 08:32
  • 1
    @Alan: Alright, followed your suggestion and added killing of the monitor. – Michael Jaros Apr 26 '16 at 08:48
11

If you have Gnu coreutils, you can use the timeout command:

timeout 1800s ./myscript

To check if the timeout occurred check the status code:

timeout 1800s ./myscript

if (($? == 124)); then
  echo "./myscript timed out after 30 minutes" >>/path/to/logfile
  exit 124
fi
rici
  • 234,347
  • 28
  • 237
  • 341