37

I have a script that tries to make a DB connection using another program and the timeout(2.5min) of the program is to long. I want to add this functionality to the script.

If it takes longer then 5 seconds to connect, kill the process
Else kill the sleep/kill process.

The issue I'm having is how bash reports when a process is killed, that's because the processes are in the same shell just the background. Is there a better way to do this or how can I silence the shell for the kill commands?

DB_CONNECTION_PROGRAM > $CONNECTFILE &
pid=$! 
(sleep 5; kill $pid) &
sleep_pid=$!
wait $pid

# If the DB failed to connect after 5 seconds and was killed
status=$? #Kill returns 128+n (fatal error)
if [ $status -gt 128 ]; then
    no_connection="ERROR: Timeout while trying to connect to $dbserver"
else # If it connected kill the sleep and any errors collect
    kill $sleep_pid
    no_connection=`sed -n '/^ERROR:/,$p' $CONNECTFILE`
fi
krizzo
  • 1,823
  • 5
  • 30
  • 52
  • I did find back old Bash scripts and they're very similar to your. I was using the bit-bucket (*/dev/null*) and *kill -9* much more liberally and I don't think there was much issue with *kill* displaying unwanted message: funnily enough that code of mine is still in use, years later, in my command prompt! (if there were display issues I'd see it in my prompt I think). It's been a long time I haven't touched it but I seems to (still) work fine. – TacticalCoder Oct 21 '11 at 21:38
  • I did recopy the meat of my Bash shell script as an answer. Hope it helps. – TacticalCoder Oct 21 '11 at 21:44
  • Take a look at this: http://redflo.de/tiki-index.php?page=Bash+script+with+timeout+function – Usman Saleem Oct 21 '11 at 22:14
  • related, requires macosx: https://stackoverflow.com/questions/601543/command-line-command-to-auto-kill-a-command-after-a-certain-amount-of-time – Ciro Santilli OurBigBook.com Apr 17 '18 at 22:05

5 Answers5

142

There's a GNU coreutils utility called timeout: http://www.gnu.org/s/coreutils/manual/html_node/timeout-invocation.html

If you have it on your platform, you could do:

timeout 5 CONNECT_TO_DB
if [ $? -eq 124 ]; then
    # Timeout occurred
else
    # No hang
fi
Itay Perl
  • 12,844
  • 3
  • 18
  • 12
11

I don't know if it's identical but I did fix a similar issue a few years ago. However I'm a programmer, not a Unix-like sysadmin so take the following with a grain of salt because my Bash-fu may not be that strong...

Basically I did fork, fork and fork : )

Out of memory After founding back my old code (which I amazingly still use daily) because my memory wasn't good enough, in Bash it worked a bit like this:

commandThatMayHang.sh 2 > /dev/null 2>&1 &    # notice that last '&', we're forking
MAYBE_HUNG_PID=$!
sleepAndMaybeKill.sh $MAYBE_HUNG_PID 2 > /dev/null 2>&1 &   # we're forking again
SLEEP_AND_MAYBE_KILL_PID=$!   
wait $MAYBE_HUNG_PID > /dev/null 2>&1
if [ $? -eq 0 ]
    # commandThatMayHand.sh did not hang, fine, no need to monitor it anymore
    kill -9 $SLEEP_AND_MAYBE_KILL 2> /dev/null 2>&1
fi

where sleepAndMaybeKill.sh sleeps the amount of time you want and then kills commandThatMayHand.sh.

So basically the two scenario are:

  1. your command exits fine (before your 5 seconds timeout or whatever) and so the wait stop as soon as your command exits fine (and kills the "killer" because it's not needed anymore

  2. the command locks up, the killer ends up killing the command

In any case you're guaranteed to either succeed as soon as the command is done or to fail after the timeout.

The Bic Pen
  • 773
  • 6
  • 21
TacticalCoder
  • 6,275
  • 3
  • 31
  • 39
  • If `./commandThatMayHang.sh` will exit before `wait`, and other process will be spawned with same pid (that is unlikely, of course, but it could happen, especially if you have something that forks very often) - that innocent process will be killed. – Anton K May 24 '18 at 12:19
  • What are the contents of `sleepAndMaybeKill.sh` file? – Richie Aug 29 '22 at 05:29
1

You can set a timeout after 2 hours and restart your javaScriptThatStalls 100 times this way in a loop

seq 100|xargs -II timeout $((2 * 60 * 60)) javaScriptThatStalls
rubo77
  • 19,527
  • 31
  • 134
  • 226
0

I found this bash script timeout.sh by Anthony Thyssen (his web). Looks good.

waseq
  • 39
  • 2
  • timeout.sh can be now found at https://antofthy.gitlab.io/software/timeout.sh.txt – Nitesh Kumar Anand Apr 13 '22 at 04:40
  • @NiteshKumarAnand the instructions are not clear. For example, if I run `./timeout.sh X npm install` the npm installation will proceed for more than X seconds. I want to be able to kill a process after X seconds. – Richie Aug 29 '22 at 05:33
0

Do you mean you don't want the error message printed if the process isn't still running? Then you could just redirect stderr: kill $pid 2>/dev/null.

You could also check whether the process is still running:

if ps -p $pid >/dev/null; then kill $pid; fi
Kevin
  • 53,822
  • 15
  • 101
  • 132
  • I want it to run and if it takes longer then 5 seconds to connect (change status) I want the PID killed. Other wise I want to stop the sleep and kill PID from even running and killing the PID since it was successful. – krizzo Oct 21 '11 at 16:06