LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash Script: Kill a process after fixed time. (https://www.linuxquestions.org/questions/linux-newbie-8/bash-script-kill-a-process-after-fixed-time-4175413756/)

bruno.miranda 06-27-2012 09:45 PM

Bash Script: Kill a process after fixed time.
 
Hello All,
I want to execute a program using a shell script, but if the program does not terminates after a certain amount of time (lets say 5 m), I want to kill it in order to execute the same program again (my program sometimes terminates before 5 min). When the program terminates I want to save its results. So, my newbie shell script is the following...

num=1
for (( i = 1; i <= 100; i++ ))
do
./MyProgram
mv result.txt /home/bruno/output_I/result_00$0.txt
((num=num+1))
done

Regards!

chrism01 06-27-2012 11:52 PM

Conceptually,
Code:

./MyProgram &

# last backgrounded job pid in $!
prog_pid=$!

# wait 5 mins
sleep 300

then use pgrep http://linux.die.net/man/1/pgrep to see if its still running

A.Thyssen 06-28-2012 01:46 AM

You hit a very complex problem, which I explored throughly in a file of shell notes, I started a very long time ago.

Go to the text file...
http://www.ict.griffith.edu.au/antho...l/script.hints
and search for...
Command Timeout

The final resulting command is called "timeout" and is available from
http://www.ict.griffith.edu.au/antho...tware/#timeout

unSpawn 06-28-2012 03:07 AM

...or given for example an executable shell script named "/usr/local/myscript" and the 'at' service being available you could run 'echo "pkill -9 -f /usr/local/myscript"|/usr/bin/at "now + 5 minutes";'.

bruno.miranda 06-28-2012 09:56 AM

Tested the following script, but using the top command I can see that MyApp is not killed at all, since it accumulates as sleeping or running process at the CPU. Any tips?

#!/bin/bash

# the application you want to terminate after a while
prog=./MyApp
num=1
# the time you want to wait before killing it
time=1s

for (( i = 1; i <= 10000; i++ ))
do
${prog} &
sleep $time
kill %1
mv result.txt /home/bruno/output_I/result_00$num.txt
((num=num+1))
done

Tinkster 06-28-2012 02:51 PM

What do you expect %1 to be? It means nothing (nothing I know of) in bash...

custangro 06-28-2012 03:00 PM

Quote:

Originally Posted by bruno.miranda (Post 4713748)
Hello All,
I want to execute a program using a shell script, but if the program does not terminates after a certain amount of time (lets say 5 m), I want to kill it in order to execute the same program again (my program sometimes terminates before 5 min). When the program terminates I want to save its results. So, my newbie shell script is the following...

num=1
for (( i = 1; i <= 100; i++ ))
do
./MyProgram
mv result.txt /home/bruno/output_I/result_00$0.txt
((num=num+1))
done

Regards!

You can try setting a ulimit

Code:


#!/bin/bash
ulimit -t 300
# the application you want to terminate after a while
prog=./MyApp
num=1
# the time you want to wait before killing it
time=1s

for (( i = 1; i <= 10000; i++ ))
do
${prog} &
sleep $time
kill %1
mv result.txt /home/bruno/output_I/result_00$num.txt
((num=num+1))
done

http://ss64.com/bash/ulimit.html

A.Thyssen 06-28-2012 07:14 PM

ulimit -t 300

whcih limits the total amount of CPU time a process (or its children) can take, before system terminates it.

The problem is unless it is a mathematical, CPU bound process, most long term processes do not use CPU, they get locked into network or disk I/O waits. Even sleep does not use any real CPU.

This means that ulimit -t does not terminate a process after 300 seconds!

It is not a practical 'timeout' technique.



As for the 'looped' sleep.

I looked at this, and as a monitor it works reasonably well but has some problems...

1/ just counting sleep times does NOT add up to real time, as it does not take into account the time for the loop to process and check if the 'monitored process' has finished. The solution for that is to compare the current time against the time you started the monitor.

2/ It has a high time granulatity. A monitored process that worked well and finished quickly will still wait the 'sleep' period before the main process continues.

3/ You do not continue immeditally when the monitored task finishes, but still waits for that last sleep cycle to finish.

4/ A loop is complex. There is no need for it unless you want to report how long you have been waiting! A single sleep should suffice.

In summery...
For long tasks, that many minutes, this will be fine.
For network tasks (DNS lookups for example) where you want to abort earily because the network has failed (a typical reason to use a timeout), it can significant.

One second many not seem like much, but it can be a long time for computers, or even users who may be waiting.



My study looked at all these things, and solved them.
(see the links above)


Turn-key solution?

Yes in a way it is. BUT I also provide all the notes of the problems discovered, and how they were solved, in that solution. Better that someone else re-inventing the wheel, when they don't want to.


ASIDE: A 'signeled sleep' between the monitor and the main process may provide a even better solution, though that is not very simple to do in shell. I tried to write it so the final "timeout" program will work even with the old bourne shell.

A C (binary) version may better, but then how do you know it has handled these problems? I looked at a number, an many were incomplete solutions. Than C programs are not always as 'portible' as it is used to be.

rknichols 06-28-2012 08:31 PM

Quote:

Originally Posted by bruno.miranda (Post 4714193)
Code:

for ((  i = 1;  i <= 10000;  i++  ))
do
  ${prog} &
  sleep $time
  kill %1
  mv result.txt /home/bruno/output_I/result_00$num.txt
  ((num=num+1))
done


Since you are immediately starting the next job and never explicitly performing a wait, the job number will not always be 1. I suggest that you use either "kill %%" or "kill %+", either of which will always refer to the most recently started background job (as will just "kill %", actually).


All times are GMT -5. The time now is 05:05 AM.