10

I have several simulations to do, each is invoked with python simulate.py <parameter list>. The problem with these simulations is that some of them hang without quiting, which prevents me from running them in batch with a simple script.

What I'd need, is some form of "run-time-constraint" command, that would automatically kill the process (preferably by virtually pressing Ctrl+C, but I think simple kill will do as well) after a specified time, if the process didn't end gracefully by itself.

Of course I can write such script myself, but I suspect that someone have done it already before me, so I don't have to reinvent the wheel spending hours with ps, time and bash manuals.

4 Answers4

16

Potential solution #1

Use the timeout command:

$ date
Mon May  6 07:35:07 EDT 2013
$ timeout 5 sleep 100
$ date
Mon May  6 07:35:14 EDT 2013

You can put a guard into the timeout command as well to kill the process if it hasn't stopped after some period of time too.

$ date
Mon May  6 07:40:40 EDT 2013
$ timeout -k 20 5 sleep 100
$ date
Mon May  6 07:40:48 EDT 2013

This will wait up to 20 seconds after the process sleep 100 should've stopped, if it's still running, then timeout will send it a kill signal.

Potential solution #2

An alternative way, though more risky method would be as follows:

./myProgram &
sleep 1
kill $! 2>/dev/null && echo "myProgram didn't finish"

Found this technique on Stack Overflow in a question titled: Limiting the time a program runs in Linux. Specifically this answer.

NOTE: Per a comment left by @mattdm the above method can be risky given it makes the assumption that there hasn't been any new processes started since your process. So no new PIDs have been assigned. Given this, this approach should probably not be used but is here only as a reference for a general approach to the problem. The timeout method is the better option of the 2.

slm
  • 369,824
  • But then it will be guaranteed, that the script will always take all that time. In my case it isn't 1 sec, but rather 15 minutes. – Adam Ryczkowski May 06 '13 at 11:27
  • But the other solution found in that question should be precisely what I need. Thanks! – Adam Ryczkowski May 06 '13 at 11:27
  • 2
    Suppose myProgram finishes in less time than sleep (not an unreasonable assumption since the goal is to set a maximum allowed runtime). You then send a signal either to a non-existent PID (no real harm done) or to any random process on the system (potentially fatal). – user May 06 '13 at 11:36
  • 1
    @MichaelKjörling, thanks for the feeback. I've updated my answer per the same comment that the OP left as well. Looks like the timeout command does exactly what he's looking for, waiting for the OP to respond to my comments. – slm May 06 '13 at 11:38
  • @slm timeout should be the solution I need. I'm testing it at the moment – Adam Ryczkowski May 06 '13 at 11:38
  • timeout is exactly what I need. – Adam Ryczkowski May 06 '13 at 11:40
  • Since PIDs are usually sequential, the chance of killing something at random when the program exits after less than a second is very low unless you have a fast machine with high abnormal activity. I certainly wouldn't do that solution for anything I was doing for anyone else or on a shared system, and in general the timeout approach is better, but on one's own system the sleep approach is effectively safe. – mattdm May 06 '13 at 15:37
  • Thanks @mattdm, incorporated your comment into the answer and also put the timeout option first to cut down on anyone finding the less optimal method down the road, and running with it 8-). – slm May 06 '13 at 17:32
  • @AdamRyczkowski, I've restructured my answer based on mattdm's feedback, let me know if that's acceptable. – slm May 06 '13 at 18:10
  • I'd still rather go with the timelimit instead of timeout. – Adam Ryczkowski May 06 '13 at 18:52
  • BTW, if timelimit is the best choice then I'd mark that one as accepted. I'm obviously motivated to push for my answer, but if that's the best answer for your question, mark that one. – slm May 06 '13 at 19:06
  • The truth is, that I wouldn't find the timelimit without you - it was you, that gave me notch in the right direction (by pointing that other SE question). So in my opinion it is fair to give you credit. – Adam Ryczkowski May 06 '13 at 20:27
4

I've found something a little better, than timeout: timelimit.

It has several advantages; one is that user can manually abort execution by pressing "Ctrl+C".

The timelimit program is available in Debian repository.

slm
  • 369,824
3

You can tune cpu time and other things with ulimit, for cpu time particularly:

$ ulimit -t 60      # limit to 60 seconds
$ program
RSFalcon7
  • 4,407
  • See this U&L Q&A: http://unix.stackexchange.com/a/4666/7453. @Gilles gives a good overview of ulimit's use for this purpose. – slm May 06 '13 at 15:51
0

Bash uses a variable called $BASHPID it can be used in such a situation, for example:

#!/bin/bash
do_face() {
    local parent=$1
    echo $BASHPID > pid
    sleep 10
    echo "Killing parent $parent"
    kill $parent
}

ME=$BASHPID
eval $(echo "do_face $ME &")
sleep 20 && kill $(cat pid) && echo "killed child $(cat pid)"
exit 1

You can change the argument in the call to sleep in do_face() to 100 instead of 10 and see what happens when the child takes too long to do his chores. Just change the call to sleep in do_face() to a call to your executable and if it takes too long then the script will kill it, 20 seconds is the limiting value in this example. Parameters can be implemented so that this becomes a simple script to call and can be called by another script in batch or whatever. Handling the pid files for each concurrent process is an issue that will need to be handled, perhaps use different sub dirs...

NB: On GNU Linux sleep can take floating point arguments such as sleep 0.1 to sleep for a tenth of a second.