pythonbashkill-process

How to kill a bash script as well as the python program started within the bash script?


I use nohup and bash scripts to help manage my python programs running on a local server. I have a bash script (tmp.sh) to invoke several python programs in a row. I try to kill the bash script and the python scripts started within the bash script with kill $PID, where PID is the process ID of the command nohup bash tmp.sh &, but only the bash script is terminated, and the python script keeps running. I don't want to export the process IDs of those python scripts because the bash script will run multiple python scripts within it and in that case I have to export the process ID of each python script.

I have created an example to reproduce the problem I have encountered.

Basically, I usually start my program by source run2.sh, which first determines if the same program is currently running to avoid duplicated running, and if not, submit a new job and change the PID to the new job in ~/.bashrc.

run2.sh

submit_a_job()
{
    nohup bash tmp.sh &
    export PID=$! # get the process ID of the above submitted job
    echo "job $PID submitted at $(date)"
    echo "job $PID submitted at $(date)" >> output.log
    echo "export PID=$!" >> ~/.bashrc
}

if [ -n "$PID" ]; then
# PID set, safe to run any job
    if ps -p $PID > /dev/null; then
    # the job is still running
        echo "$PID is running, new job not submitted"
    else
    # the job has finished, delete previous PID, and submit a new job
        echo "$PID is finished, new job submitted"
        sed -i '/PID/d' ~/.bashrc
        submit_a_job
    fi
else
# PID not set, the job might still be running or have finished
    echo "helloworld"
    submit_a_job
fi

If you do not want to modify ~/.bashrc, you can comment off the following lines in run2.sh. And make sure you run run2.sh with source, otherwise the environment variable is not exported to the current working shell.

echo "export PID=$!" >> ~/.bashrc
sed -i '/PID/d' ~/.bashrc

tmp.sh is the script that runs python jobs

time python3 while.py

while.py is just a meaningless dead loop

import time

counter = 0

while True:
    print(f"This is an infinite loop! Iteration: {counter}", flush=True)
    counter += 1
    time.sleep(1)  # Sleep for 1 second between iterations

As I have exported the ID of the process that runs bash tmp.sh as PID, I can kill the bash script tmp.sh with command kill $PID. The problem is, even if tmp.sh no longer runs, the python script that runs at the time I kill tmp.sh keeps running in the background. I can confirm this point by command ps aux | grep python3, which clearly indicates while.py is running.

Which command should I use to kill the bash script tmp.sh as well as the python program running at the same time I kill tmp.sh?


Solution

  • Kill the whole process group, rather than just the shell process.

    kill -INT -$PID
    

    When you give a negative PID to kill, it treats it as a process group ID.