0

I start a python script and then after some time i want to kill it. but before killing it I want to start another copy of this same script and then kill the previous one after starting new one. I want to do this in loop.

here is my code , i just need a clean way to kill scripts.I do not want to use timeouts.

#!/bin/bash 
while true
do
    echo "starting FIRST Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &

    sleep 20
    echo "starting SECOND Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    # Here I want to kill FIRST Consumer.py
    sleep 20
    # Here I want to kill SECOND Consumer.py

done
6
  • Any reason you don't want to use timeout 20 python3 ... ? man7.org/linux/man-pages/man1/timeout.1.html Commented Jan 29, 2019 at 13:19
  • yes i was using timeouts but sometimes it doesnt kill my scripts. but starts new ones. after some time i had 8 scripts running. Commented Jan 29, 2019 at 13:21
  • Are you sure about the comments in your code sample? (did you invert SECOND and FIRST ?) Commented Jan 29, 2019 at 13:24
  • i have edited the comments :p Commented Jan 29, 2019 at 13:26
  • 1
    Clean and kill are kind of conflicting requirements. Where kill means "stop at any cost", and clean meaning "exit gracefully" . If you're program isn't exiting after a SIGTERM signal then it is misbehaving. Fix your python script before resorting to using SIGKILL. Downsides to using SIGKILL include losing state if the process isn't able to save state about what has been consumed. Commented Jan 29, 2019 at 13:45

4 Answers 4

2

You can get the PID of the first process to kill it afterwards:

#!/bin/bash 

while true
do
    echo "starting FIRST Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    pid=$!
    sleep 20

    echo "starting SECOND Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    new_pid=$!

    # Here I want to kill FIRST Consumer.py
    kill "$pid"
    sleep 20

    # Here I want to kill SECOND Consumer.py
    kill "$new_pid"
done
Sign up to request clarification or add additional context in comments.

2 Comments

this answer worked for me but when i added -9 to kill command kill -9 "$pid"
This detail depends on what are you trying to kill. By default, kill sends a SIGTERM signal (15), and this signal can be catched and processed. It is supposed to give the application a chance to write down it's status and exit grecefully. But if it does not exit, you can always use the SIGKILL (9), which cannot be trapped and forces the system to kill the application.
2

In bash there are two special background jobs: + and -. You can see them in the output of the jobs command:

$ sleep 10 &
$ sleep 20 &
$ sleep 30 &
$ jobs
[1]   Running                 sleep 10 &
[2]-  Running                 sleep 20 &
[3]+  Running                 sleep 30 &

+ is the most recent running job. - is the most recent job before +. Both will update if you kill a job or start a new one. Therefore you could complete your script as follows:

#!/bin/bash 
while true; do
    echo "starting FIRST Consumer.py : $(date +%T)"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    sleep 20
    echo "starting SECOND Consumer.py : $(date +%T)"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    kill %- # kill FIRST Consumer.py
    sleep 20
    kill %+ # kill SECOND Consumer.py
done

This only works reliably if Consumer.py always runs longer than 20 seconds. If Consumer.py could terminate before the 20 second are over, then we may kill the wrong job. To work around this issue, you can use (python3 .../Consumer.py; sleep inf) & instead of python3 .../Consumer.py &. The sleep inf will stop the job from terminating on its own.

Comments

2

Each time a background process is started, bash maintains a jobs list, with ids starting from 1.

The jobs builtin lists the background jobs.

in you situation, you would add the kill %1 to kill the first background job ever started, and then kill %2

== EDITED == Your script becomes:

#!/bin/bash 
while : ; do
   echo "starting FIRST Consumer.py : $(date +"%T")"
   python3 /home/irum/Desktop/Marketsyc/Consumer.py &

   sleep 20
   echo "starting SECOND Consumer.py : $(date +"%T")"
   python3 /home/irum/Desktop/Marketsyc/Consumer.py &

   kill %1

   sleep 20

   kill %2

   wait
 done

9 Comments

The job ids always increase. %1 and %2 are only correct for the first iteration. In the second iteration you would have to use %3 and %4. You can access the PID (not job id) of the last job with $!.
@Socowi: as the loop is ending without any background jobs, the ids are always 1 and 2. This is confirmed with my tests.
Are you sure? I tested my claim in bash 4.4.19(1) and 5.0.0(1) on two different systems. For me, the following script quickly prints numbers > 2. while :; do sleep 10 & sleep 20 & kill %1; kill %2; jobs | wc -l; done.
Maybe you are right nevertheless. sleep 1 & kill %1; sleep 2 & jobs creates the job ids %1 and %2, but sleep 1 & kill %1; sleep 0.5; sleep 2 & jobs uses the job id %1 twice. Seems like kill is asynchronous and we need a small pause between killing an old job and starting a new one such that the old job id is freed before the new job is started.
This small quirks are the reason I prefer to work with PIDs in scripts. Interactive job management is another beast.
|
0

I would do this

    #!/bin/bash 
function check_pid() {
    if /bin/ps -p $1 > /dev/null
    then
        kill $1
    else
        echo "not running"
    fi
}

while true
do
    echo "starting FIRST Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    pid1=$!
    sleep 20
    echo "starting SECOND Consumer.py : $(date +"%T")"
    python3 /home/irum/Desktop/Marketsyc/Consumer.py &
    pid2=$!
    # Here I want to kill FIRST Consumer.py
    check_pid $pid1
    sleep 20
    # Here I want to kill SECOND Consumer.py
    check_pid $pid2
done

In this way, the process will be killed only if it is still running.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.