5

I'm trying to write a script which greps for a running process.

I'm trying to avoid the actual grep from coming back from the ps aux output.

However I'm getting varying results if I use a dot or not:

ps aux | grep [s]elenium doesn't return anything.

ps aux | grep [s]elenium.jar returns the grep command:

beebee   36155  0.0  0.0  15940   956 pts/0    S+   16:20   0:00 grep --color=auto selenium.jar

Why is that?

Braiam
  • 69,112
Beebee
  • 153

3 Answers3

12

I guess you have a file named selenium.jar but no file called selenium in your current folder.

If you run

 ps aux | grep [s]elenium.jar

the shell will try to replace [s]elenium.jar with matching files names from the current folder. If there is a file called selenium.jar that will match and [s]elenium.jar will be replaced by selenium.jar.

The shell will then execute the command with the replaced value, i.e.

ps aux | grep selenium.jar

To avoid this quote the regex to protect it from the shell:

ps aux | grep '[s]elenium.jar'
5

The problem here, as @Florian perceptively figured out, is that the shell is expanding the glob characters in your search string to a matching filename before passing the string on to grep.

Running ps aux | grep foo is problematic since the grep foo command itself will match foo and so appear in the output. There are two common, if convoluted, workarounds for this. You either add a grep -v grep at the end of the pipe, or you use grep [f]oo instead. Since grep works with regular expressions, it will treat [f] as "any character in the list of characters inside the brackets". Since the only character in the brackets is f, [f]oo is equivalent to foo. However, the grep process showing up in the ps results will have the string [f]oo and is, therefore, not found by grep.

This becomes more complicated if, as seems to be the case for you, you have a file called foo in your current directory. Because you haven't quoted the expression you gave to grep (because you used [s]elenium and not '[s]elenium' or "[s]elenium"), the shell will treat it as a glob and expand it to the matching file name. This renders the [s]elenium trick useless since what is actually passed to grep is selenium and not [s]elenium so the grep will match itself.

All this, however, only happens because you're not using the right tool for the job. As is so often the case, there's an app for that! Don't use grep + ps. Instead, use pgrep which is designed to do precisely what you want:

NAME
       pgrep,  pkill  -  look  up  or signal processes based on name and other
       attributes

SYNOPSIS
       pgrep [options] pattern
       pkill [options] pattern

DESCRIPTION
       pgrep looks through the  currently  running  processes  and  lists  the
       process IDs which match the selection criteria to stdout.  All the cri‐
       teria have to match.  For example,

         $ pgrep -u root sshd

So, in your case, you can just do

pgrep selenium

Or, since you're running it via java, use -f which searches through the entire command line:

pgrep -f selenium
terdon
  • 104,119
2

You could exclude the "grep" after the initial grep:

ps aux | grep '[s]elenium.jar' | grep -v grep
drew
  • 21