Bash Shell Awesomeness – Mass Killing Processes (On Ubuntu)

by Alan Skorkin on August 6, 2009

I am not a Linux newbie, but neither am I an expert. So, I sometimes tend to come across some really cool stuff and I just have to share.

Here is the story. We use this application at work (I won’t point any fingers :)) which tends to run as a whole lot of processes when it starts up, and these processes don’t all have the same parent process either. Once in a while this application can get into a bad state where you have to manually kill all the processes to restart everything. Now as you might imagine this can be a bit of a pain since there are quite a few processes even if you only count the parents.

Here is where some bash magic comes to the rescue. Luckily for us, this application runs as a separate Linux user so all the processes have the same user id and we’re able to use the following command to kill everything in one fell swoop.

ps -ef | grep ^1002 | cut -c 5-15 | sudo xargs kill

Here is a quick rundown of what it does:

  • the ps command is obvious, we get the processes that are currently active
  • we pipe the output to grep in order to find all the lines that begin with a particular id (this is the id of the user that runs the application)
  • we then pipe the output of that to the cut command to pull out characters 5 to 15 of every line (i.e. the process id will live in that character range)
  • we then pipe the output of that to xargs which lets us use each line of that output as an argument to the kill command, thereby killing all those processes (the sudo bit is really optional and you would use it only if your current user didn’t have permission to kill the processes)

Update: As Sam pointed out in the comments below kill -9 should only ever be used as a last resort as it will create ‘orphaned shared memory segments’ and is therefore best avoided if possible

I don’t know about you, but I thought that was pretty cool :). The only side-effect is that all processes owned by that particular user will get killed (i.e. if you have a shell opened as that user).

I wonder if there is an easier way of doing this with bash? And it would also be great if we didn’t have to kill all processes owned by a user, but rather could mass-kill a bunch of processes based on some other criteria. If anyone is a bash expert, feel free to supply some tips :).

Update: Apparently, according to the comments, there are a number of way of doing this, using either a shorter pipeline or even just one command that would even let you pick particular processes based on criteria (e.g. pkill). Have a look through the comments for details. Thanks to all the commenters for the great feedback!

{ 1 trackback }

Destillat KW33-2009 | duetsch.info - GNU/Linux, Open Source, Softwareentwicklung, Selbstmanagement, Vim ...
August 14, 2009 at 9:59 pm

{ 37 comments… read them below or add one }

Jeremy August 6, 2009 at 9:54 pm

I guess if I think fast enough, I might be able to guess what that troublesome application is. Is it something I can search on, perhaps?

Reply

Alan Skorkin August 6, 2009 at 9:58 pm

I do recall it having features that could be called search related :). Deductive force is strong with you :).

Reply

Mike Adolphs August 6, 2009 at 10:15 pm

I’d stick to killall rather than piping through 4 different commands. Basically it’s the same as “cat abc|grep xyz” or “grep xyz abc”. Both solutions work just fine, but one solution is nicer.
However, in the end the only thing that matters is whether it works or not and both ways do.

Reply

Alan Skorkin August 6, 2009 at 10:18 pm

Thanks for the tip, I’ll definitely have a look at killall. But, yeah like you said, as long as it works. It just blows my mind a little that one can do so much with what amounts to a one-liner.

Reply

PiX August 6, 2009 at 10:20 pm

Simplicity…..
$ killall -u user

Reply

Alan Skorkin August 6, 2009 at 10:49 pm

Ahh, good one. What would be powerful though if you could supply some kind of criteria or even a regex to the command rather than killing all processes belonging to a user. It looks like you can do:

killall -u user -c procname

But it doesn’t look like procname can be a regex.

Reply

anon August 6, 2009 at 10:52 pm

Useless use of grep there… the -u option in ps lets you specify only processes used by some $USERNAME

ps -fu $USERNAME | awk ‘{print $2}’ | sudo xargs kill -9

Reply

Alan Skorkin August 6, 2009 at 10:54 pm

Hmmm, awk, thats another great one (why didn’t I think of that :)). Cheers for that.

Reply

Michael Bubb August 6, 2009 at 10:53 pm

Hello – what about something like:

for i in `pgrep appname`
do
kill $i;
done

I use this on occasion with a backup program that spawns a number of related processes and hangs…

Reply

Alan Skorkin August 6, 2009 at 10:57 pm

That’s great:
pgrep – sounds like a really handy one to know about

Reply

Luca Beltrame August 6, 2009 at 11:25 pm

I think “pkill” does also pattern matching.

Reply

Alan Skorkin August 6, 2009 at 11:27 pm

Well, there we go, I just knew linux would have the tools I envisioned.

Reply

pbhj August 6, 2009 at 10:55 pm

Doesn’t Alt+SysRq+K do the same thing – kills all active user processes. Plus you don’t need to be able to open a console to get it.

IIRC it’s now disabled by default in some Linux distros (Ubuntu at least) and so you may need to make some config changes to enable is. Try Alt+SysRq+H to get help info.

Reply

Alan Skorkin August 6, 2009 at 11:08 pm

That is also a great tip and a novel (at least to me) way of looking at the problem. Thanks for sharing.

Reply

Parag Shah August 6, 2009 at 10:55 pm

Thanks, I will use this for some scripts.

Reply

Alan Skorkin August 6, 2009 at 11:08 pm

You’re welcome

Reply

Jack August 6, 2009 at 10:56 pm

Been using: ps -ef | grep foo | awk “{print $1}” | xargs kill … for systems without killall for years. Not news to me but glad people are finally starting to Feel the Power. Of course, I’ve been a unix/linux admin for going on 16 years now :-)

Reply

Alan Skorkin August 6, 2009 at 11:10 pm

Yeah, the more I use linux the more I keep finding some really cool stuff that you can do with it :)

Reply

Øyvind Grønnesby August 6, 2009 at 11:25 pm

pgrep also has the associated pkill, which will send a signal to all matching processes.

Reply

Alan Skorkin August 6, 2009 at 11:29 pm

Thanks, looks like a very handy one that one and seems to be exactly what I was after, will need to go try it out now.

Reply

chanux August 6, 2009 at 11:34 pm

‘ps -u alan’ will filter processes by user ID alan :)
And you should check this site http://www.commandlinefu.com

Reply

Alan Skorkin August 7, 2009 at 10:31 am

That looks like a useful site, cheers for sharing.

Reply

heretic August 6, 2009 at 11:44 pm

Others have been there, done that (and with more flexibility too boot): http://www.perlmonks.com/?node_id=448715

Reply

Alan Skorkin August 7, 2009 at 10:32 am

That looks like a nice perl script, although massive overkill for the problem that I needed to solve.

Reply

Sam August 7, 2009 at 12:26 am

Anyone who thinks using “kill -9″ as a default is awesome clearly doesn’t understand UNIX or Linux.

Welcome to orphaned shared memory segment hell. You get to reboot to get that memory back.

Reply

Alan Skorkin August 7, 2009 at 10:42 am

Thanks for sharing the info, I wasn’t aware that kill -9 would do that, of source when kill by itself doesn’t work, what choice do you have?

Reply

Sam August 7, 2009 at 12:28 pm

You have many choices. Read the kill man page and learn about signals. Perhaps your poorly behaving app responds to HUP. -9 is a last resort and you should update this post to reflect that as you’re just spreading bad ideas.

Reply

Alan Skorkin August 7, 2009 at 12:39 pm

That’s a good idea I will update the post to reflect the fact that -9 is only to be used as a last resort. Cheers for the feedback.

Reply

Alejandro Segovia August 7, 2009 at 1:00 am

Yet another one; cheers ;)

kill -9 $(ps u -u $USERNAME | awk ‘{print $2}’)

Reply

Alan Skorkin August 7, 2009 at 10:33 am

Hehe, thanks!

Reply

Ben Beecher August 7, 2009 at 1:45 am

The xarg is unnecessary. Kill can take a list of processes to kill -

ps -ef | grep ^1002 | cut -c 5-15 | sudo xargs kill -9

can become

kill -9 `ps -ef | grep ^1002 | cut -c 5-15 `

(Or $(foo) if you prefer)

Reply

Alan Skorkin August 7, 2009 at 10:33 am

Ahh, thats a useful shortcut as well, thanks.

Reply

ericb August 7, 2009 at 3:08 am

While it is cool, your example has nothing to do with Bash.

Reply

Matt August 7, 2009 at 4:53 am

This post is definitely offensive. You should probably clarify the danger of your post.

If you run almost all of these commands on an application run by root, you will receive undefined results. In this case, undefined results probably means that you will crash your system.

That said, here is how to do it on less forgiving OSes that do not mandate the use of sudo:

On a UNIX and most non-Ubuntu Linux systems, this is equivalent:

kill -9 `ps -ef | grep [username_string] | awk ‘{print $2}’`

If you’re on Unix and you want to do it by UID (which would be preferable as these are predefined in the passwd file) , you can do this:

kill -9 `ptree [UID] | awk ‘{print $1}’`

(linux equivalient is pstree)

This will kill all children and the parent.

Run a second ps -ef after the fact to search for possible zombies. If you are using this advice in a script and do not reap the zombie processes, your admin will become agitated.
Ps -ef does not show all running processes, so the examples given here may miss children of all processes that were found.

The easy way:

You will use far less CPU cycles simply killing the shell (or parent process, depending) for the user running the application.

Example:

kill -9 [ID of user shell or parent process].

Kill -9 should not be used on a first attempt as if it attempts to SIGHUP a process that is performing writes or a system-critical process, you will likely corrupt data. Using a simple kill is a safe interrupt level (SIGTERM) to use in a script for killing process – if something is performing a system critical operation, the process will not be killed.

A request was made for a method to avoid killing the actual shell or parent process in a bash shell. Do the following:

Linux:

kill `pstree [parent PID, or UID] | grep -v [parent PID, or UID]`

this may also work:

kill `pstree ([parent PID, or UID]) | grep -v $1`

I honestly can’t remember what shell that works with haha, bourne, maybe? I’ll let you know.

Reply

Alan Skorkin August 7, 2009 at 10:36 am

Thanks for the detailed explanation, it is much appreciated. I didn’t intend this post as expert advice on linux shell usage, just something we did at work that I thought was cool. The real benefit is when others come along and expand on the ideas, present better ways and warn of dangers (like you have done and others as well) in the comments. That way everyone gets to learn more.

Reply

Anon August 7, 2009 at 5:43 am

We tend to have the same issue with a tomcat4 webapp, I generally use:

ps aux | grep tomcat4 | awk ‘{print $2}’ | xargs kill -9

This way you can specify the pid of any processes which you are grepping for, and kill them all without killing all other processes that belong to that user, that is assuming that they all run under a similar process executable.

Reply

Alan Skorkin August 7, 2009 at 10:38 am

Yeah that would work as well, but like you said they do all have to have something similar to grep for.

Reply

Leave a Comment

Previous post:

Next post: