Coder Perfect

In Bash, how do I kill a child process after a timeout?

Problem

As a result, I’d like to be able to start this process for a certain period of time and then kill it if it doesn’t return properly after that time.

Is there an easy and reliable way to accomplish this with bash?

P.S. Please let me know if this is a better question for serverfault or superuser.

Asked by Greg

Solution #1

(See BASH FAQ #68, “How do I run a command and have it abort (timeout) after N seconds?”)

If you don’t mind waiting for something to download, install timeout (sudo apt-get install timeout) and use it as follows: (most Systems have it already installed otherwise use sudo apt-get install coreutils)

timeout 10 ping www.goooooogle.com

If you don’t want to download something, do what timeout does internally:

( cmdpid=$BASHPID; (sleep 10; kill $cmdpid) & exec ping www.goooooogle.com )

If you wish to do a timeout for a lengthier bash code, go with the second option:

( cmdpid=$BASHPID; 
    (sleep 10; kill $cmdpid) \
   & while ! ping -w 1 www.goooooogle.com 
     do 
         echo crap; 
     done )

Answered by Ignacio Vazquez-Abrams

Solution #2

# Spawn a child process:
(dosmth) & pid=$!
# in the background, sleep for 10 secs then kill that process
(sleep 10 && kill -9 $pid) &

Alternatively, alternatively, to obtain the exit codes:

# Spawn a child process:
(dosmth) & pid=$!
# in the background, sleep for 10 secs then kill that process
(sleep 10 && kill -9 $pid) & waiter=$!
# wait on our worker process and return the exitcode
exitcode=$(wait $pid && echo $?)
# kill the waiter subshell, if it still runs
kill -9 $waiter 2>/dev/null
# 0 if we killed the waiter, cause that means the process finished before the waiter
finished_gracefully=$?

Answered by Dan

Solution #3

sleep 999&
t=$!
sleep 10
kill $t

Answered by DigitalRoss

Solution #4

I had the same question and discovered two additional resources that were quite helpful:

So, on the command line (OSX 10.9), I use something like this:

ping www.goooooogle.com & PING_PID=$(pgrep 'ping'); SECONDS=0; while pgrep -q 'ping'; do sleep 0.2; if [ $SECONDS = 10 ]; then kill $PING_PID; fi; done

Because this is a loop, I included a “sleep 0.2” to keep the CPU from overheating.

(By the way, ping is a horrible example; you’d just use the built-in “-t” (timeout) option instead.)

Answered by Ulrich

Solution #5

If you already have (or can easily construct) a pid file to track the child’s pid, you may write a script that checks the pid file’s modtime and kills/respawns the process as needed. Then just add the script to crontab and schedule it to execute at the time you require.

Let me know if you need more details. If that doesn’t sound like it’ll work for you, how about trying upstart?

Answered by kojiro

Post is based on https://stackoverflow.com/questions/5161193/how-to-kill-a-child-process-after-a-given-timeout-in-bash