grep invading my ps
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:
- Invoke
ps
. - Buffer all of its output (because it has nowhere else to go yet).
- Invoke
grep
. - Feed the saved output to
grep
'sstdin
.
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).
Related videos on Youtube
che
My name is Eimantas. I am Cocoa developer from Lithuania. Sometimes I tweet. Mandatory #SOreadytohelp
Updated on September 18, 2022Comments
-
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 afterps
has run? -
Lekensteyn over 9 years
[my]process.
would matchmprocessX
andyprocessY
(since[my]
is a character class which matches on of the lettersm
ory
, and.
matches anything). -
iyrin over 9 yearsIf you want to maintain color highlighting of the matched string use
ps | grep --color=always myprocess | grep -v grep
-
Overmind Jiang over 9 yearsDo you mean "You're incorrect"? The rest continues as if that's what you mean.
-
Rob C over 9 years@RyanLoremIpsum Or just reorder the two grep commands like
ps -ef | grep -v grep | grep myprocess
-
iyrin over 9 yearsSo inconsistent. Why does it work that way and not the other? v_v
-
Marco Ceppi over 9 yearsBecause the colors are being stripped in the pipeline
-
mhars over 9 yearsA time-honored trick to help this is
ps -ef|grep [m]yprocess
-
iyrin over 9 years
pgrep -a
does not seem to be available to me inpgrep -V
pgrep from procps-ng 3.3.3
. -
Sreeraj over 9 years@RyanLoremIpsum - Did you check the
man
page.