Saturday, March 29, 2008

Trick grep not to report itself in a process search

How often have you searched for a process, using ps and grep?

$ ps -ef |grep emacs
peter 7107 1 1 09:10 ? 00:00:08 /usr/bin/emacs-snapshot-gtk
peter 7377 7050 0 09:19 pts/0 00:00:00 grep emacs

It always reports one more process than you want to see ... namely the grep process itself.

In the example above, the process 7377 is the grep process itself. What you really want is the 7107 emacs process.

While this is really harmless (albeit annoying), it can be a real pain if you put this in a script. In that case, you have to parse out the grep process itself.

You can trick grep not to report itself by enclosing a character in the search string in square brackets:
$ ps -ef |grep emac[s]
peter 7107 1 1 09:10 ? 00:00:10 /usr/bin/emacs-snapshot-gtk

Square brackets in bash are character matching patterns. emac[s] will only match the string emacs.

StumbleUpon Toolbar


aht said...

I use pgrep/pkill

Brian Kuebler said...

I know that this post has been out there for a while, but this just came in really handy! Thanks for the tip.

obat said...

This is great, now I can use it for Nagios service check.

Heaps thanks

Eric Chang said...

Thanks, that's amazing. But why does it work? Wouldn't emacs[s] also match "grep emacs"? I'm so confused

Peter Leung said...

you should grep for emac[s], NOT emacs[s].

Normally, 'ps|grep emacs' will report itself because it matches the emacs argument to the grep command.
But the square brackets will take care of that.


Anonymous said...

Peter, I think you misunderstood Eric's question.

Eric, the reason that it works is because the grep process doesn't contain the string emacs any more.

You're now running
grep emac[s]
And emac[s] doesn't contain the string emacs (which is what grepping for emac[s] looks for.)

Does that make sense?

Brian Bay said...

You can also use grep's exclusion option:

grep -v grep

drbao said...

Eric asked why "|grep emac[s]" worked without displaying grep string itself? Answers given here do not actually helps to understand.

Actually, ERIC`s question is quite smart, if he thought as I suppose he did :)

And I suppose, first he red:

"""Square brackets in bash are character matching patterns. emac[s] will only match the string emacs."""

...and then he thought:

If BASH is the one who parses regular expression "emac[s]", then BOTH strings must be presented in output. BOTH. Because GREP utility received not "emac[s]" but "emacs", as BASH parsed RE before pass it to GREP. So, actual "ps" string for "grep emacs" must looked like: "grep emacs", and NOT LIKE "grep emac[s]" and because there would not square bracked presented BOTH strings must be in output!"

But such a regular expression looses sense, of course.
GREP must understand RE (regular expression) itself, instead of receive substituted literal string from BASH.

RE isn`t BASH`s invention. BASH is only one of application environments that use it. RE are IEEE POSIX standart, after all. Grep (as a part of GNU family tools) uses it, too. As PHP, Apache does.


[x@y ~]# ps aux |grep 'ini[t]'
root ... init [3]
root ... init [3]
root ... init [3]
root ... init [3]
root ... init [3]
root ... init [3]
root ... init [3]
root ... init [3]

Noticed those ''? in case BASH parsed that RE we`d get only one output: grep 'ini[t]'

BTW, GREP has 4 RE style modes.Read about GREP keys -G -F -E -P) and command shortcuts of egrep fgrep pgrep.

Anonymous said...

Somehow this trick did not work for me on Fedora 13 ( Desktop).
I had to use grep -v grep option. That is

ps -ef | grep init | grep -v grep

exh said...

For those who use zsh we need to made it like: ps -ef |grep 'emac[s]'

Re-reading man 1 ps I founded:

-C cmdlist Select by command name

So, what about "ps -fC emacs" ?

Good to read your blog.

Irakli said...

This was a lifesaver tip. Thank you!

Anonymous said...

Very useful, also works with awk:

ps aux | awk '/skyp[e]/{print $2}'


Alwin said...

As I was getting a bit anoid by all the non-answers given here to the question 'why does grep emac[s] work', here is the real answer:

The regular expression (the s inside the square brackets) matches a character set which contains a single character (the character s in this case) and the literal string "emac".
Grep does not self-match the original regular expression string ('grep emac[s]'), because that string also includes the square brackets.
i.e. the word 'emacs' does not appear in the original command given: 'grep emac[s]'

Anonymous said...

emacs{1} pattern works as well =)

Karthikeyan S said...

drbao, you are great.. thanks for the explanation...

Pavan BhavaniShekhar Devarakonda said...

Drbao, it helped me to write more optimastic script for my weblogic scripts :)