How could I make a script time out after nn minutes, if it's not finished by then?
The practical context: I have a dozen or so of backup scripts in a directory "daily", and they are run by cron like this:
0 23 * * 1-6 run-parts /root/daily
Sometimes one of the scripts hang, in which case the rest of the scripts are delayed more than can be allowed.
- Jussi
-- Jussi Hirvi * Green Spot
NOTICE: Due to the rising energy costs, as well as current market conditions, the Light at the End of the Tunnel has been turned off. We apologise for the inconvenience.
Jussi Hirvi wrote:
How could I make a script time out after nn minutes, if it's not finished by then?
I put this little test script together. It seems to work OK... #!/bin/bash timeoutseconds=5 pid=$$ (echo Will kill $pid in $timeoutseconds seconds; sleep $timeoutseconds; kill -1 $pid) & while true do echo Hello sleep 0.6 done
You may need to vary the signal in the kill statement, depending on what you're running.
Ian
Ian Blackwell (ian@ikel.id.au) kirjoitteli (12.11.2008 12:13):
I put this little test script together. It seems to work OK... #!/bin/bash timeoutseconds=5 pid=$$ (echo Will kill $pid in $timeoutseconds seconds; sleep $timeoutseconds; kill -1 $pid) & while true do echo Hello sleep 0.6 done
You may need to vary the signal in the kill statement, depending on what you're running.
Hei,
Thanks - but I couldn't make that work as expected. It seems to kill *something*, but after that, the rsync part still continues in the background... Here's my last test:
log='/root/log/rsync2' timeoutseconds=1 pid=$$ (sleep $timeoutseconds; echo `date '+%c'` " $0 INTERRUPTED" >>$log; kill -9 $pid) & /usr/bin/rsync -avzu --delete /root /home/palvelimet/bckserver1 echo `date '+%c'` " $0 valmis" >>$log
Then I found this, which leads me to believe it's not that simple:
http://www.cit.gu.edu.au/~anthony/info/shell/script.hints
(scroll to "Command timeout")
On that page, they recommend "a simple c solution" timeout.c, which you can download here:
ftp.kaist.ac.kr/NetBSD/NetBSD-current/src/lib/libcurses/timeout.c
Anybody bother to comment? How is that thing used? Sorry, I don't speak c.
Regards, Jussi
-- Jussi Hirvi * Green Spot Topeliuksenkatu 15 C * 00250 Helsinki * Finland Tel. & fax +358 9 493 981 * Mobile +358 40 771 2098 (only sms) jussi.hirvi@greenspot.fi * http://www.greenspot.fi
Hi,
On Wed, Nov 12, 2008 at 08:39, Jussi Hirvi greenspot@greenspot.fi wrote:
Thanks - but I couldn't make that work as expected. It seems to kill *something*, but after that, the rsync part still continues in the background...
If what you want to kill is the rsync process, do the opposite, run rsync in background, sleep for some time, test if it is still running and then kill it.
Here's my last test:
log='/root/log/rsync2' timeoutseconds=1 pid=$$ (sleep $timeoutseconds; echo `date '+%c'` " $0 INTERRUPTED" >>$log; kill -9 $pid) & /usr/bin/rsync -avzu --delete /root /home/palvelimet/bckserver1 echo `date '+%c'` " $0 valmis" >>$log
Use something like:
#! /bin/bash timeout=60 /usr/bin/rsync -avzu --delete /root /home/palvelimet/bckserver1 & rsync_pid=$? sleep "$timeout" # test if process $rsync_pid is still a child of this process: ppid_rsync=`ps -o ppid= "$rsync_pid"` # remove any spaces ppid_rsync=`echo $ppid_rsync` # compare the parent of $rsync_pid with this process, if it matches, kill $rsync_pid test x"$ppid_rsync" = x"$$" && kill "$rsync_pid"
It's certainly more convoluted than it should be... but it should work.
The C solution is probably the right thing to do, if you have time to dig into it and find out how it works.
HTH, Filipe
Or maybe the next script that cron executes can kill the previous one as a first step before doing anything else.
--Amos
On 11/13/08, Filipe Brandenburger filbranden@gmail.com wrote:
Hi,
On Wed, Nov 12, 2008 at 08:39, Jussi Hirvi greenspot@greenspot.fi wrote:
Thanks - but I couldn't make that work as expected. It seems to kill *something*, but after that, the rsync part still continues in the background...
If what you want to kill is the rsync process, do the opposite, run rsync in background, sleep for some time, test if it is still running and then kill it.
Here's my last test:
log='/root/log/rsync2' timeoutseconds=1 pid=$$ (sleep $timeoutseconds; echo `date '+%c'` " $0 INTERRUPTED" >>$log; kill -9 $pid) & /usr/bin/rsync -avzu --delete /root /home/palvelimet/bckserver1 echo `date '+%c'` " $0 valmis" >>$log
Use something like:
#! /bin/bash timeout=60 /usr/bin/rsync -avzu --delete /root /home/palvelimet/bckserver1 & rsync_pid=$? sleep "$timeout" # test if process $rsync_pid is still a child of this process: ppid_rsync=`ps -o ppid= "$rsync_pid"` # remove any spaces ppid_rsync=`echo $ppid_rsync` # compare the parent of $rsync_pid with this process, if it matches, kill $rsync_pid test x"$ppid_rsync" = x"$$" && kill "$rsync_pid"
It's certainly more convoluted than it should be... but it should work.
The C solution is probably the right thing to do, if you have time to dig into it and find out how it works.
HTH, Filipe _______________________________________________ CentOS mailing list CentOS@centos.org http://lists.centos.org/mailman/listinfo/centos
Jussi Hirvi wrote:
Thanks - but I couldn't make that work as expected. It seems to kill *something*, but after that, the rsync part still continues in the background... Here's my last test:
log='/root/log/rsync2' timeoutseconds=1 pid=$$ (sleep $timeoutseconds; echo `date '+%c'` " $0 INTERRUPTED" >>$log; kill -9 $pid) & /usr/bin/rsync -avzu --delete /root /home/palvelimet/bckserver1 echo `date '+%c'` " $0 valmis" >>$log
Try replacing the 'kill -9 $pid' with '/usr/bin/kill -s KILL -$pid'
I've used something based on:
http://www.splode.com/~friedman/software/scripts/src/with-timeout
which seems to work fine
James Pearson
On Wed, 2008-11-12 at 11:54 +0200, Jussi Hirvi wrote:
How could I make a script time out after nn minutes, if it's not finished by then?
The practical context: I have a dozen or so of backup scripts in a directory "daily", and they are run by cron like this:
0 23 * * 1-6 run-parts /root/daily
Sometimes one of the scripts hang, in which case the rest of the scripts are delayed more than can be allowed.
Do "man bash" and search for "trap". For those not familiar, it can be a little confusing, but it's well worth the effort, in terms of results and learning.
- Jussi
<snip sig stuff>
HTH
On Wed, 2008-11-12 at 05:37 -0500, William L. Maltby wrote:
On Wed, 2008-11-12 at 11:54 +0200, Jussi Hirvi wrote:
How could I make a script time out after nn minutes, if it's not finished by then?
<snip>
Do "man bash" and search for "trap". For those not familiar, it can be a little confusing, but it's well worth the effort, in terms of results and learning.
<*sigh*>
Well, it seems that bash doesn't have some of the stuff ISTR from the original *IX stuff (builtin alarm? not sure anymore). Anyway, a google for "bash alarm trap" led to this and there are lots more. This was just the first and may not be the best for your needs.
http://steve-parker.org/sh/trap.shtml
Anyway, sans "alarm", a trap, sleep, SIGUSR* or SIGINT combination should do nicely.
HTH