Find and kill a process in one line using bash and regex
Solution 1:
In bash
, you should be able to do:
kill $(ps aux | grep '[p]ython csp_build.py' | awk '{print $2}')
Details on its workings are as follows:
- The
ps
gives you the list of all the processes. - The
grep
filters that based on your search string,[p]
is a trick to stop you picking up the actualgrep
process itself. - The
awk
just gives you the second field of each line, which is the PID. - The
$(x)
construct means to executex
then take its output and put it on the command line. The output of thatps
pipeline inside that construct above is the list of process IDs so you end up with a command likekill 1234 1122 7654
.
Here's a transcript showing it in action:
pax> sleep 3600 &
[1] 2225
pax> sleep 3600 &
[2] 2226
pax> sleep 3600 &
[3] 2227
pax> sleep 3600 &
[4] 2228
pax> sleep 3600 &
[5] 2229
pax> kill $(ps aux | grep '[s]leep' | awk '{print $2}')
[5]+ Terminated sleep 3600
[1] Terminated sleep 3600
[2] Terminated sleep 3600
[3]- Terminated sleep 3600
[4]+ Terminated sleep 3600
and you can see it terminating all the sleepers.
Explaining the grep '[p]ython csp_build.py'
bit in a bit more detail:
When you do sleep 3600 &
followed by ps -ef | grep sleep
, you tend to get two processes with sleep
in it, the sleep 3600
and the grep sleep
(because they both have sleep
in them, that's not rocket science).
However, ps -ef | grep '[s]leep'
won't create a process with sleep
in it, it instead creates grep '[s]leep'
and here's the tricky bit: the grep
doesn't find it because it's looking for the regular expression "any character from the character class [s]
(which is s
) followed by leep
.
In other words, it's looking for sleep
but the grep process is grep '[s]leep'
which doesn't have sleep
in it.
When I was shown this (by someone here on SO), I immediately started using it because
- it's one less process than adding
| grep -v grep
; and - it's elegant and sneaky, a rare combination :-)
Solution 2:
if you have pkill,
pkill -f csp_build.py
If you only want to grep against the process name (instead of the full argument list) then leave off -f
.
Solution 3:
One liner:
ps aux | grep -i csp_build | awk '{print $2}' | xargs sudo kill -9
- Print out column 2:
awk '{print $2}'
-
sudo
is optional - Run
kill -9 5124
,kill -9 5373
etc (kill -15 is more graceful but slightly slower)
Bonus:
I also have 2 shortcut functions defined in my .bash_profile (~/.bash_profile is for osx, you have to see what works for your *nix machine).
-
p keyword
- lists out all Processes containing keyword
- usage e.g:
p csp_build
,p python
etc
bash_profile code:
# FIND PROCESS
function p(){
ps aux | grep -i $1 | grep -v grep
}
-
ka keyword
- Kills All processes that have this keyword
- usage e.g:
ka csp_build
,ka python
etc - optional kill level e.g:
ka csp_build 15
,ka python 9
bash_profile code:
# KILL ALL
function ka(){
cnt=$( p $1 | wc -l) # total count of processes found
klevel=${2:-15} # kill level, defaults to 15 if argument 2 is empty
echo -e "\nSearching for '$1' -- Found" $cnt "Running Processes .. "
p $1
echo -e '\nTerminating' $cnt 'processes .. '
ps aux | grep -i $1 | grep -v grep | awk '{print $2}' | xargs sudo kill -klevel
echo -e "Done!\n"
echo "Running search again:"
p "$1"
echo -e "\n"
}
Solution 4:
killall -r regexp
-r, --regexp
Interpret process name pattern as an extended regular expression.