Reputation: 1295
I want to kill all processes containing some string. I wrote script for doing this. However, when I execute it, it gets "Killed" signal after first iteration of for loop. This is my code:
#!/bin/bash
executeCommand () {
local pname="$1";
echo $HOSTNAME;
local search_terms=($(ps aux | grep $pname | awk '{print $2}'))
for pros in "${search_terms[@]}"; do
kill -9 "$pros"
echo $pros
done
exit
}
executeCommand "$1" # get the string that process to be killed contains
I execute it like ./my_script.sh zookeeper
.
When I delete the line containing kill
command, for loop
executes until end, otherwise, after first kill
command, I get as an output "Killed
" and program exits.
What is possible reason for this, and any other solution to reach my goal?
Upvotes: 0
Views: 5052
Reputation: 151
grep will show , it's own process . it should be removed using grep -v option
Try like this
for i in ` ps -ef | grep "$pname" | grep -v grep | awk '{print $2}'`
do
kill -9 $i
done
Upvotes: 0
Reputation: 295629
The silly (faulty, buggy) way to do this is to add grep -v grep
to your pipeline:
# ${0##*/} expands to the name of the running script
# ...thus, we avoid killing either grep, or the script itself
ps aux | grep -e "$pname" | egrep -v "grep|${0##*/}" | awk '{print $2}'
The better way is to use a tool built for the job:
# pkill already, automatically, avoids killing any of its parent processes
pkill "$pname"
That said, matching processes by name is a bad practice to start with -- you'll also kill less yourproc.log
or vim yourproc.conf
, not just yourproc
. Don't do it; instead, use a proper process supervision system (upstart, DJB daemontools, Apple launchd, systemd, etc) to monitor your long-running daemons and kill or restart them when needed.
By the way -- there's no need for a for
loop at all: kill
can be passed multiple PIDs on a single invocation, like so:
# a bit longer and bash-specific, but avoids globbing
IFS=$'\n' read -r -d '' -a pids \
< <(ps auxw | awk -v proc="$pname" -v preserve="${0##*/}" \
'$0 ~ proc && $0 !~ preserve && ! /awk/ { print $2 }' \
&& printf '\0')
kill -- "${pids[@]}"
...which could also be formulated as something like:
# setting IFS and running `set -f` necessary to make unquoted expansion safe
( IFS=$'\n'; set -f; exec kill -- \
$(ps auxw | awk -v proc="$pname" -v preserve="${0##*/}" \
'$0 ~ proc && $0 !~ preserve && ! /awk/ { print $2 }') )
Upvotes: 4