6

I have a bash script doing a lot of things called script.sh:

#!/bin/bash
#It
#Is
#Doing
#Things

Is there a way that I can get the process ID of this script from within itself, and then kill it after 5 minutes?

Like:

#!/bin/bash
#Get pid of script.sh here, start a 5 minute timer and kill the script after time runs out
#It
#Is
#Doing
#Things
2
  • 5
    mywiki.wooledge.org/XyProblem ;)
    – n.st
    May 18 '14 at 13:58
  • uset timeout, redirect output to a file (maybe in /tmp, if it is on ram you get better performance) and tail -f that file.
    – Lesto
    May 19 '14 at 9:17
11

If you always want the script to timeout after 5 minutes, you can simply use a block in a background process like this. If you use Ctrl+C while it's running, the background process will also terminate:

#!/bin/bash
{
    sleep 5m
    kill $$
} &

while true
do
    date
    sleep 1
done
5
  • Thank you..this is a good answer but doesn't work in my case
    – MLSC
    May 19 '14 at 12:55
  • 2
    ...Well, why not?
    – user41277
    May 19 '14 at 12:56
  • Owww...I saw your edited answer now...This is working absolutely...Thank you very much...
    – MLSC
    May 19 '14 at 13:00
  • If you check via ps command , parent script and sleep are still running. Not recommended
    – django
    Oct 8 '20 at 6:17
  • @django It works as-described for me. Run the script, Ctrl+C, run ps, and the background sleep process is terminated.
    – user41277
    Oct 9 '20 at 16:50
20

The timeout utility that is a part of GNU coreutils does it for you:

timeout 5m bash script.sh

would terminate the script after 5 minutes of execution.

5
  • Pardon but there is a problem..while my script is running it shows me output..but in your case this is not do that..Imagin you have infinitive while loop that echo sth...when I do what you said it doesn't show me output and my machine hangs...
    – MLSC
    May 18 '14 at 16:21
  • 2
    Works fine for me. I made a script consisting mostly of while : ; do echo hello ; done then ran timeout 1s bash ./thatscript.sh -- it printed "hello" a large number of times and terminated after about a second, as expected.
    – user
    May 19 '14 at 11:20
  • I tested it and My system broke down :), I don't know why!!!
    – MLSC
    May 19 '14 at 13:27
  • @MortezaLSC I'm not sure what happens in your case. This is a pretty standard utility designed for the very purpose.
    – devnull
    May 19 '14 at 13:30
  • Thank you very much @devnull . I used your answer and of course it is helping me...Thank you very much
    – MLSC
    May 19 '14 at 18:59
14

You get the PID with PID=$$.

What you want may be most easily achieved with the command timeout.

But you can run a background process, too:

(sleep $TIMEOUT && kill "$PID") &
5
  • Pardon but there is a problem..while my script is running it shows me output..but in your case this is not do that..Imagin you have infinitive while loop that echo sth...when I do what you said it doesn't show me output and my machine hangs...
    – MLSC
    May 18 '14 at 16:20
  • @MortezaLSC I have given you two suggestions. What exactly have you done? May 18 '14 at 19:25
  • see Gnouc's answer, This is my script and please see my update as well..Thank you very much
    – MLSC
    May 18 '14 at 19:30
  • You see...It brings my script to background...while my script is running it shows sth in terminal runtime..
    – MLSC
    May 18 '14 at 19:32
  • 1
    I think you still need to add & at the end to actually send it to the background. The brackets only start a subshell.
    – Darkhogg
    May 18 '14 at 22:58
5

You could change your loop to:

#!/bin/bash -
SECONDS=0
while ((SECONDS < 5*60))
do
  echo "line printed"
done

Or insert ((SECONDS < 5*60)) || exit within your deepest loop.

SECONDS in ksh, zsh and bash is a special variables that gets incremented every second.

5
  • I think your answer is one of the best one..but I would be thankful and your answer would be accepted if you help me, This is my script . Where should I put your aswer here? Thank you very much
    – MLSC
    May 19 '14 at 11:18
  • Your answer is the sth like Gnouc's answer and both are correct really...but in my case I confused...doesn't work
    – MLSC
    May 19 '14 at 11:27
  • @MortezaLSC, your script is missing the #! /bin/bash - line so would be executed by sh. May 19 '14 at 12:58
  • No..I put the whole script into your while loop with #!/bin/bash - and doesn't work as well...please see blujay's answer.. It is working well
    – MLSC
    May 19 '14 at 13:02
  • Didn't know such variable existed. As always, learned something new from your answers Mar 8 '17 at 23:25
4

You can use a check condition:

#!/bin/bash

START=$(date +%s)

while [[ $(($(date +%s) - $START)) -lt 300 ]]
do
    #do something here
done

echo QUIT

Explanation

  • date +%s get the time in seconds since epoch, we save it to START variable, mark start time of script.
  • [[ $(($(date +%s) - $START)) -lt 300 ]]: we get current time (date +%s again) subtract to start time (which is saved in START variable).
  • If the result is less than 300 (5 minutes), script continue running,
  • If the result is equal to or greater than 300, meaning script has run 5 minutes since start time, we quit the while loop, script ends.
4
  • Thank you..My script has infinitive loop...if I put my whole script into your while loop do you think it works? Thank you
    – MLSC
    May 18 '14 at 19:10
  • I think you must use my while loop instead of your infinitive loop to make it works. Can you give more details about your script?
    – cuonglm
    May 18 '14 at 19:12
  • +1 This is my script
    – MLSC
    May 18 '14 at 19:15
  • Your answer is the sth like Stephane Chazelas's answer and both are correct really...but in my case I confused...doesn't work
    – MLSC
    May 19 '14 at 11:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.