27

I want to write a shell script (.sh file) to get a given process id. What I'm trying to do here is once I get the process ID, I want to kill that process. I'm running on Ubuntu (Linux).

I was able to do it with a command like

ps -aux|grep ruby
kill -9 <pid>

but I'm not sure how to do it through a shell script.

Zombo
  • 1
  • 62
  • 391
  • 407
sameera207
  • 16,547
  • 19
  • 87
  • 152
  • 4
    Okay, amuse me. *Why* do you want to use `kill -9` on it? – Ignacio Vazquez-Abrams Jun 22 '11 at 09:21
  • 1
    @Konstantin imagine you want to kill a Java process. You might have several java processes running and this way you cannot use "killall java" as you would kill every process – frandevel Apr 28 '13 at 08:36
  • To expand on @IgnacioVazquez-Abrams' comment, unless you *know* the process doesn't have a signal handler and/or is broken and doesn't respect regular `kill`, this is a [useless use of `kill -9`](http://www.iki.fi/era/unix/award.html#kill) – tripleee Nov 25 '17 at 12:43

9 Answers9

37

Using grep on the results of ps is a bad idea in a script, since some proportion of the time it will also match the grep process you've just invoked. The command pgrep avoids this problem, so if you need to know the process ID, that's a better option. (Note that, of course, there may be many processes matched.)

However, in your example, you could just use the similar command pkill to kill all matching processes:

pkill ruby

Incidentally, you should be aware that using -9 is overkill (ho ho) in almost every case - there's some useful advice about that in the text of the "Useless Use of kill -9 form letter ":

No no no. Don't use kill -9.

It doesn't give the process a chance to cleanly:

  1. shut down socket connections
  2. clean up temp files
  3. inform its children that it is going away
  4. reset its terminal characteristics

and so on and so on and so on.

Generally, send 15, and wait a second or two, and if that doesn't work, send 2, and if that doesn't work, send 1. If that doesn't, REMOVE THE BINARY because the program is badly behaved!

Don't use kill -9. Don't bring out the combine harvester just to tidy up the flower pot.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
  • Wish I could use this, `bash-4.2# pgrep bash: pgrep: command not found` :( – SSH This Jun 20 '13 at 22:14
  • @SSHThis: what operating systems / distribution and version are you using? (pgrep / pkill are distributed in procps on Linux-based systems.) – Mark Longair Jun 21 '13 at 05:09
  • I am on AIX, I basically had just pass the process id as an argument to my script and find it prior to running it. Not a big deal for my case, thanks for the extra info tho :) – SSH This Jun 21 '13 at 14:49
  • The meaning of `15`, `2`, `1` signals should be included - or at least a link to read about them: http://www.linux.org/threads/kill-signals-and-commands-revised.8096/ – MrMeszaros Apr 19 '17 at 19:26
17

If you are going to use ps and grep then you should do it this way:

ps aux|grep r[u]by

Those square brackets will cause grep to skip the line for the grep command itself. So to use this in a script do:

output=`ps aux|grep r\[u\]by`
set -- $output
pid=$2
kill $pid
sleep 2
kill -9 $pid >/dev/null 2>&1

The backticks allow you to capture the output of a comand in a shell variable. The set -- parses the ps output into words, and $2 is the second word on the line which happens to be the pid. Then you send a TERM signal, wait a couple of seconds for ruby to to shut itself down, then kill it mercilessly if it still exists, but throw away any output because most of the time kill -9 will complain that the process is already dead.

I know that I have used this without the backslashes before the square brackets but just now I checked it on Ubuntu 12 and it seems to require them. This probably has something to do with bash's many options and the default config on different Linux distros. Hopefully the [ and ] will work anywhere but I no longer have access to the servers where I know that it worked without backslash so I cannot be sure.

One comment suggests grep-v and that is what I used to do, but then when I learned of the [] variant, I decided it was better to spawn one fewer process in the pipeline.

Michael Dillon
  • 31,973
  • 6
  • 70
  • 106
  • 2
    this is a fantastic example gets your pid for you, though I think it should be $2 and not $1, some corrections are below: output=`ps -aux|grep r[u]by`;set -- $output;pid=$2;kill $pid;sleep 2;kill -9 $pid >/dev/null 2>&1 – bjhaid Sep 24 '12 at 13:38
  • Thank you for a great explanation! Could you also explain the magic behind r[u]by please? :) – johnjohn Oct 19 '12 at 22:32
  • 2
    The grep command doesn't search for a string, it searches for a regular expression. And square brackets are used to supply a set of characters, any one of which will match the pattern. Of course a set of one single character will only match that character, and since ps displays the original command line contents with the square brackets, this regular expression will not match that command line. – Michael Dillon Oct 20 '12 at 03:23
  • 2
    A more explicit way to exclude the grep command itself 'ps aux | grep ruby | grep -v grep – notbrain Feb 10 '13 at 02:50
  • I didn't know about set --. Thanks ! – Jean-Philippe Caruana Oct 18 '13 at 12:46
  • The backslashes in the script cannot be used on CentOS 6.4 it seems. I did put the regex in double quotes as well, maybe that has something to do with it (like this: output=`ps aux | grep "[r]uby"`) – Wim Deblauwe Feb 21 '14 at 09:15
7

As a start there is no need to do a ps -aux | grep... The command pidof is far better to use. And almost never ever do kill -9 see here

to get the output from a command in bash, use something like

pid=$(pidof ruby)

or use pkill directly.

Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
  • 1
    ps -aux works on more different systems so it is worthwhile to know this. And I used kill -9 precisely to show the correct usage. First you use kill -15 and only when that fails, use kill -9. The sleep 2 is there to give the application a reasonable amount of time to clean up and shutdown from receiving the signal to do so. – Michael Dillon Oct 20 '12 at 03:25
  • Another thing to note is that the grep technique also allows you to narrow down the search to a particular command, not just the process name. – thomas-peter Dec 02 '14 at 14:35
  • **Simple is better !** If it is not already there I will prefer to install instead of using hard to remember and complex commands. – Nasir Iqbal Feb 19 '15 at 05:37
4

option -v is very important. It can exclude a grep expression itself

e.g.

ps -w | grep sshd | grep -v grep | awk '{print $1}' to get sshd id
Dimitar
  • 4,402
  • 4
  • 31
  • 47
user2223691
  • 57
  • 1
  • 1
  • As always, piping `grep` to Awk is [useless](http://www.iki.fi/era/unix/award.html#grep). A much better solution, like in Steven Penny's answer, is to use Awk alone. `ps -w | awk '/sshd/ { print $1 }'` and maybe throw in Michael Dillon's regex trick, or better yet restrict the match to a single field `ps -w | awk '$4 == "sshd" { print $1 }'` ... though of course we are still reinventing `pidof`, poorly. – tripleee Nov 24 '17 at 08:05
3

This works in Cygwin but it should be effective in Linux as well.

ps -W | awk '/ruby/,NF=1' | xargs kill -f

or

ps -W | awk '$0~z,NF=1' z=ruby | xargs kill -f

Bash Pitfalls

Zombo
  • 1
  • 62
  • 391
  • 407
2

You can use the command killall:

$ killall ruby
Francisco R
  • 4,032
  • 1
  • 22
  • 37
0

Its pretty simple. Simply Run Any Program like this :- x= gedit & echo $! this will give you PID of this process. then do this kill -9 $x

abhishekrana
  • 144
  • 1
  • 9
-1

To kill the process in shell

getprocess=`ps -ef|grep servername`
#echo $getprocess
set $getprocess 
pid=$2
#echo $pid
kill -9 $pid
para
  • 29
  • 2
-1

If you already know the process then this will be useful:

PID=`ps -eaf | grep <process> | grep -v grep | awk '{print $2}'`
if [[ "" !=  "$PID" ]]; then
echo "killing $PID"
kill -9 $PID
fi
Francis
  • 94
  • 10