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?
Kill the whole process group, rather than just the shell process.
When you give a negative PID to
kill, it treats it as a process group ID.