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
  • 67,791
  • 32
  • 179
  • 269
Beebee
  • 153
  • You're matching exact string with s character followed elenium. Actual string contains more than that. Since it's jar file it begins with java command. My approach would be just to match selenium string and pipe into grep -v grep to remove grep command itself – Sergiy Kolodyazhnyy Jun 15 '16 at 15:30

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'
  • I see, I've just tested this and it's exactly as you described. I didn't know that the shell will mess with a piped grep! Thanks. – Beebee Jun 15 '16 at 15:40
  • Do you have a reference for that? I didn't know that filenames in the current folder could be substituted in a grep regex, and I can't find it in man grep, for instance. – Jos Jun 15 '16 at 15:42
  • 3
    @Jos: This isn't a function of grep but of the shell: When you run a command in the shell the shell first splits it into "words" and then tries to expand each "word" according to some rules. See the "EXPANSION" section of the bash manpage – Florian Diesch Jun 15 '16 at 15:52
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
  • 100,812
  • I've tried pgrep, but i'm running selenium through java -jar so it's not finding it. See here: http://askubuntu.com/questions/157075/why-does-ps-aux-grep-x-give-better-results-than-pgrep-x – Beebee Jun 15 '16 at 16:32
  • pgrep has -f flag which lets you use full command line to be searched. Try pgrep -f selenium – Sergiy Kolodyazhnyy Jun 15 '16 at 16:36
  • @Beebee what Serg said. You need -f to search through the entire comman line and not only the executable launched (java). – terdon Jun 15 '16 at 16:47
  • Since his problem was shell expansion of what it thought was the filename he provided on the command line, so he would have run into problems with pgrep as well. – Johnny Jun 15 '16 at 20:48
  • @johnny No he wouldn't. The shell only meddles with the string because it contains meta characters (the square brackets). You would not need them with pgrep. – Dubu Jun 15 '16 at 21:05
  • 1
    @johnny what Dubuque said. The only reason the shell was expanding the search string is because it had glob characters so the shell treated is as a glob. The only reason it had glob characters was because they are a classic trick to stop grep from appearing in the the output when parsing ps. And the only reason that grep was needed was because ps was being parsed. All of these problems disappear if you use pgrep which is designed for precisely this function. – terdon Jun 15 '16 at 21:14
  • @terdon This "the only reason" chain is crucial to the value of your answer and to even understanding why the heck the OP as using the brackets to begin with. It would help if you moved this explanation into your answer, perhaps at the very beginning; it would really help clarify and motivate your answer. At first I thought your answer was an irrelevant tangent, but this explanation finally makes it clear. – Don Hatch Jun 16 '16 at 08:24
  • @DonHatch as @terdon said "The only reason it had glob characters was because they are a classic trick to stop grep from appearing in the the output when parsing ps.". I'm trying to write a script to start selenium standalone server if it's not already started. I was using a bash script to ps aux | grep for selenium and start it if there's no output. – Beebee Jun 16 '16 at 08:53
  • @DonHatch is that better? – terdon Jun 16 '16 at 09:25
2

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

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