grep invading my ps

5,972

Solution 1

This behavior is totally normal, it's due to how bash manages pipe usage.

pipe is implemented by bash using the pipe syscall. After that call, bash forks and replaces the standard input (file descriptor 0) with the input from the right process (grep). The main bash process creates another fork and passes the output descriptor of the fifo in place of the standard input (file description 1) and launches the left command.

The ps utility is launched after the grep command, so you can see it on the output.

If you are not convinced by it, you can use set -x to enable command tracing. For instance:

+ ps aux
+ grep --color=auto grep
+ grep --color=auto systemd
alexises  1094  0.0  0.8   6212  2196 pts/0    S+   09:30   0:00 grep --color=auto systemd

For more explanation you can check this part of basic c shell: http://www.cs.loyola.edu/~jglenn/702/S2005/Examples/dup2.html

Solution 2

When I'm only interested in presence of a process, I use pgrep which doesn't show this behaviour, e.g.:

$ pgrep myprocess
1900

In other cases (when I'm interested in more info), I usually add a | grep -v grep to discard grep lines, e.g.:

$ ps -ef | grep myprocess| grep -v grep

Solution 3

The pipe does not behave like ;. It starts both the processes together. Which is why the grep command showed up too. So when you gave ps aux | grep myprocess , the ps aux included the grep myprocess, so the grep included that in its output.

To check this, I gave two dd commands on my test server like this:

[sreeraj@server ~]$ dd if=/dev/urandom of=/home/sreeraj/myfile1 bs=1M count=1024 | dd  if=/dev/urandom of=/home/sreeraj/myfile2 bs=1M count=1024

And when I checked for the dd process, it shows that it both has started at the same time(look at the coloumn that says 2:55 minutes has elapsed) :

[sreeraj@server ~]$ ps aux | grep 'dd if'
sreeraj  14891  100  0.2   5376  1416 pts/0    R+   11:56   2:55 dd if=/dev/urandom of=/home/sreeraj/myfile1 bs=1M count=1024
sreeraj  14892  100  0.2   5376  1412 pts/0    R+   11:56   2:55 dd if=/dev/urandom of=/home/sreeraj/myfile2 bs=1M count=1024
sreeraj  14936  0.0  0.1   9032   672 pts/1    S+   11:59   0:00 grep --color=auto dd if
[sreeraj@server ~]$

Now, if you want to exclude the grep from getting outputted, use regex. It will exclude the grep from the result:

ps aux | grep "[m]yprocess"

For example, if you are looking for httpd process, use:

ps aux | grep "[h]ttpd"

But I suggest you use pgrep -a, which will be more reliable.

[sreeraj@server ~]$ pgrep -a httpd
8507 /usr/sbin/httpd -DFOREGROUND
8509 /usr/sbin/httpd -DFOREGROUND
8510 /usr/sbin/httpd -DFOREGROUND
8511 /usr/sbin/httpd -DFOREGROUND
8513 /usr/sbin/httpd -DFOREGROUND
8529 /usr/sbin/httpd -DFOREGROUND
[sreeraj@server ~]$

Solution 4

You're correct, that's not how it works. The shell doesn't wait for the first process in a pipeline to exit before starting the next. It starts them all. As such, the ps may see the grep already running.

Solution 5

Consider this thought experiment: if ps ran to completion before invoking grep as you think it should, that would mean that the shell would need to:

  1. Invoke ps.
  2. Buffer all of its output (because it has nowhere else to go yet).
  3. Invoke grep.
  4. Feed the saved output to grep's stdin.

This is wasteful; it's a more efficient use of memory to invoke grep first, let it wait for input, then feed ps's stdout directly to grep's stdin.

Or, taken to the extreme, consider the case of piping the output of a program that generates an infinite amount of output, e.g.:

$ yes | less

If the shell ran yes before less, you would be left waiting forever (or until you completely exhaust your computer's memory).

Share:
5,972

Related videos on Youtube

che
Author by

che

My name is Eimantas. I am Cocoa developer from Lithuania. Sometimes I tweet. Mandatory #SOreadytohelp

Updated on September 18, 2022

Comments

  • che
    che almost 2 years

    When I'm checking for some process, I usually write

    ps aux | grep myprocess
    

    And sometimes I get the output of

    eimantas 11998  0.0  0.0   8816   740 pts/0    S+   07:45   0:00 grep myprocess
    

    if the process is not running.

    Now I really wonder why grep is in the list of processes if it filters out the output of the ps command after ps has run?

  • Lekensteyn
    Lekensteyn over 9 years
    [my]process. would match mprocessX and yprocessY (since [my] is a character class which matches on of the letters m or y, and . matches anything).
  • iyrin
    iyrin over 9 years
    If you want to maintain color highlighting of the matched string use ps | grep --color=always myprocess | grep -v grep
  • Overmind Jiang
    Overmind Jiang over 9 years
    Do you mean "You're incorrect"? The rest continues as if that's what you mean.
  • Rob C
    Rob C over 9 years
    @RyanLoremIpsum Or just reorder the two grep commands like ps -ef | grep -v grep | grep myprocess
  • iyrin
    iyrin over 9 years
    So inconsistent. Why does it work that way and not the other? v_v
  • Marco Ceppi
    Marco Ceppi over 9 years
    Because the colors are being stripped in the pipeline
  • mhars
    mhars over 9 years
    A time-honored trick to help this is ps -ef|grep [m]yprocess
  • iyrin
    iyrin over 9 years
    pgrep -a does not seem to be available to me in pgrep -V pgrep from procps-ng 3.3.3.
  • Sreeraj
    Sreeraj over 9 years
    @RyanLoremIpsum - Did you check the man page.