I want to kill the background process belonging to a shell script that I am going to run again.
That means before executing the shell script I want to delete the background process running for the same script.
I want to kill the background process belonging to a shell script that I am going to run again.
That means before executing the shell script I want to delete the background process running for the same script.
Check for the existence of a PID from the same script.
add this at the beginning of the script:
#!/bin/bash
script_name=${BASH_SOURCE[0]}
for pid in $(pidof -x $script_name); do
if [ $pid != $$ ]; then
kill -9 $pid
fi
done
kill -9
is usually overkill(!), and can lead to system instability. https://unix.stackexchange.com/questions/8916/when-should-i-not-kill-9-a-process
– drkvogel
May 14 '22 at 12:38
kill -9 $(pgrep -f ${BASH_SOURCE[0]} | grep -v $$)
Very simple.
Uses pgrep to search for all instances of the currently running script.
pgrep is nice since it only returns pids.
Then grep out the currently running pid using $$, so it won't suicide.
Finally kill -9 terminates the previous instances.
I did this a long time back in one of my shell scripts. Here is how I did it:
ps aux | \
grep -P ${BASH_SOURCE[0]} | \
grep -v $$ | \
grep -P "bash" | \
grep -oP "^[[:alnum:]]+\s+\d+\s" | \
grep -oP "\d+" | \
xargs kill -9
The beauty of this method is that it will NOT kill the current running script itself, only the previous instances of it.
A sample script to demonstrate the above method is this:
#!/bin/bash
ps aux | grep -P ${BASH_SOURCE[0]} | grep -v $$ | grep -P "bash" | grep -oP "^[[:alnum:]]+\s+\d+\s" | grep -oP "\d+"
sleep 100
Now, run one instance of this script in your terminal. And then run another instance in a different terminal. You will see that the previous instance will be immediately killed while the second one runs fine.
kill -9 $(pgrep -f ${BASH_SOURCE[0]} | grep -v $$)
Very simple. Uses pgrep to search for all instances of the currently running script. pgrep is nice since it only returns pids. Then grep out the currently running pid, so it won't suicide. Finally kill -9 terminates the previous instances.
You can use $0
instead of ${BASH_SOURCE[0]}
.
I had to use pgrep -f <filename>
instead of pidof -x <filename>
because for some reason the latter wasn't returning anything.
Also, kill -9
isn't needed here.
So the result (inspired by @jcbermy's answer):
#!/bin/bash
for pid in $(pgrep -f $0); do
if [ $pid != $$ ]; then
kill $pid
fi
done
Try this:
#!/bin/sh
if [ -f /var/run/sh.pid ]; then
echo "Process already running."
kill -9 `cat /var/run/sh.pid`
rm -f /var/run/sh.pid
fi
echo `pidof $$` > /var/run/sh.pid
# From here, your normal shell script can resume
this one is shorter and worked for me in my ruby app
ps -ef| grep search_pattern | awk '{print $2}' | xargs kill -9
replace search_pattern with the name of your script
grep
and awk
is redundant; Awk does pattern matching. pgrep
would be an even simpler approach...
– jasonwryan
Jun 11 '16 at 06:45
command=$(ps -p $$ -o args --no-headers)
kill -9 $(pgrep -fx "$command" | grep -v $$) || true # kill processes with command, except own process
Most answers use ${BASH_SOURCE[0]}
, which is only the path of the script. Not the entire command. For me, it was killing too much, e.g. the editor editing the script.
You get the entire command of the current process with ps -p $$ -o args --no-headers
. With pgrep -fx
you can exactly match (-x
) the full command (-f
) and return all process ids. grep -v $$
removes the process id of the current process. kill -9
kills those processes. If there is no process to be killed, don't fail by adding || true
.
Solution which also take into considerations Process descendants and works with cron
# Current PGID
pgid_current=$(ps -o pgid= $$ | tr -d ' ')
Kill all other PGID's
for pid in $(pgrep -f $0); do
pgid=$(ps -o pgid= "${pid}" | tr -d ' ')
if [[ -n "${pgid}" && "${pgid}" != "${pgid_current}" ]]; then
log "Kill pgid ${pgid}"
kill -15 -"${pgid}"
fi
done
current execution PGID
- ps -o pgid= $$
all PID's based on the executed script name
- pgrep -f $0
all PGID's of the found PID's
- ps -o pgid= "${pid}"
found PGID is not empty
- -n "${pgid}"
(already killed) and not equal to the current execution PGID
- != "${pgid_current}"
PGID's
by sending SIGTERM
- kill -<signal> -<PGID>
test.sh
#!/bin/bash
Show last processes
echo
ps xao pid,ppid,pgid,sid,user,group,start_time,comm,args | (head -n1 && tail -n10)
Current execution
echo
echo "Script Name: $0"
echo "Script PID: $$"
echo "Script PID pgrep: pgrep -d ' ' -f $0
"
echo "Script PPID: $PPID"
echo "Script PPID via ps: ps -o ppid= $$ | tr -d ' '
"
echo "Script SID via ps: ps -o sid= $$ | tr -d ' '
"
echo
crontab -l
*/1 * * * * bash /opt/test.sh >>/opt/cron.log 2>&1
tail -f /opt/cron.log
PID PPID PGID SID USER GROUP START COMMAND COMMAND
1176 1175 1176 1175 root root 10:02 bash /bin/bash
1297 2 0 0 root root 10:06 kworker/0:0-cgr [kworker/0:0-cgroup_destroy]
1299 2 0 0 root root 10:07 kworker/u4:0-fl [kworker/u4:0-flush-259:0]
1543 2 0 0 root root 10:15 kworker/1:2-mm_ [kworker/1:2-mm_percpu_wq]
1658 2 0 0 root root 10:21 kworker/u4:1-ev [kworker/u4:1-events_power_efficient]
3191 437 437 437 root root 11:21 cron /usr/sbin/CRON -f -P
3192 3191 3192 3192 root root 11:21 sh /bin/sh -c bash /opt/test.sh 2>&1 >>/opt/cron.log
3193 3192 3192 3192 root root 11:21 bash bash /opt/test.sh
3194 3193 3192 3192 root root 11:21 ps ps xao pid,ppid,pgid,sid,user,group,start_time,comm,args
3195 3193 3192 3192 root root 11:21 bash bash /opt/test.sh
Script Name: /opt/test.sh
Script PID: 3193
Script PID pgrep: 3192 3193
Script PPID: 3192
Script PPID via ps: 3192
Script PGID via ps: 3192
Script SID via ps: 3192
Execution order - PID < PPID > PGID
Cron: 3191 < 437 > 437
--> sh: 3192 < 3191 > 3192
--> bash: 3193 < 3192 > 3192
--> ps: 3194 < 3193 > 3192
cron (3191) --> sh (3192) --> bash (3193) --> ps (3194)
\ ____ ____ / __________ /
\ /
|
sh (3192)
kill -9
which should never be used routinely. Instead, send the default signal; this allows the victim to perform any required cleanup before proceeding to do an orderly shutdown. – tripleee Oct 06 '19 at 13:39