1

I would like to use the timeout command with an own function, e.g.:

#!/bin/bash
function test { sleep 10; echo "done" }

timeout 5 test

But when calling this script, it seems to do nothing. The shell returns right after I started it.

Is there a way to fix this or can timeout not be used on own functions ?

dkb
  • 4,389
  • 4
  • 36
  • 54
John Threepwood
  • 15,593
  • 27
  • 93
  • 149
  • What is the `timeout` command? It's not a built-in of bash. – Aaron Digulla Aug 13 '12 at 13:27
  • Few more answers from another SOF link: [execute function with timeout](https://stackoverflow.com/questions/9954794/execute-function-with-timeout) – dkb Feb 01 '16 at 06:56

5 Answers5

4

One way is to do

timeout 5 bash -c 'sleep 10; echo "done"'

instead. Though you can also hack up something like this:

f() { sleep 10; echo done; }
f & pid=$!
{ sleep 5; kill $pid; } &
wait $pid
geirha
  • 5,801
  • 1
  • 30
  • 35
3

timeout doesn't seem to be a built-in command of bash which means it can't access functions. You will have to move the function body into a new script file and pass it to timeout as parameter.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
3

timeout requires a command and can't work on shell functions.

Unfortunately your function above has a name clash with the /usr/bin/test executable, and that's causing some confusion, since /usr/bin/test exits immediately. If you rename your function to (say) t, you'll see:

brian@machine:~/$ timeout t
Try `timeout --help' for more information.

which isn't hugely helpful, but serves to illustrate what's going on.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
1

Found this question when trying to achieve this myself, and working from @geirha's answer, I got the following to work:

#!/usr/bin/env bash
# "thisfile" contains full path to this script
thisfile=$(readlink -ne "${BASH_SOURCE[0]}")

# the function to timeout
func1()
{ 
  echo "this is func1"; 
  sleep 60
}

### MAIN ###
# only execute 'main' if this file is not being source
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
   #timeout func1 after 2 sec, even though it will sleep for 60 sec
   timeout 2 bash -c "source $thisfile && func1"
fi

Since timeout executes the command its given in a new shell, the trick was getting that subshell environment to source the script to inherit the function you want to run. The second trick was to make it somewhat readable..., which led to the thisfile variable.

0

Provided you isolate your function in a separate script, you can do it this way:

(sleep 1m && killall myfunction.sh) & # we schedule timeout 1 mn here
myfunction.sh
Stephane Rouberol
  • 4,286
  • 19
  • 18