When I do
$ ps -ef | grep cron
I get
root 1036 1 0 Jul28 ? 00:00:00 cron
abc 21025 14334 0 19:15 pts/2 00:00:00 grep --color=auto cron
My question is why do I see the second line. From my understanding, ps lists the processes and pipes the list to grep. grep hasn’t even started running while ps is listing processes, then how come grep process is listed in the o/p ?
Related second question:
When I do
$ ps -ef | grep [c]ron
I get only
root 1036 1 0 Jul28 ? 00:00:00 cron
What is the difference between first and second grep executions?
When you execute the command:
the shell you are using
(…I assume bash in your case, due to the color attribute of grep I think you are running a gnu system like a linux distribution, but it’s the same on other unix/shell as well…)
will execute the
pipe()call to create a FIFO, then it willfork()(make a running copy of itself). This will create a new child process. This new generated child process willclose()its standard output file descriptor (fd 1) and attach the fd 1 to the write side of the pipe created by the father process (the shell where you executed the command). This is possible because thefork()syscall will maintain, for each, a valid open file descriptor (the pipe fd in this case). After doing so it willexec()the first (in your case)pscommand found in yourPATHenvironment variable. With theexec()call the process will become the command you executed.So, you now have the shell process with a child that is, in your case, the
pscommand with-efattributes.At this point, the parent (the shell)
fork()s again. This newly generated child processclose()s its standard input file descriptor (fd 0) and attaches the fd 0 to the read side of the pipe created by the father process (the shell where you executed the command).After doing so it will
exec()the first (in your case)grepcommand found in your PATH environment variable.Now you have the shell process with two children (that are siblings) where the first one is the
pscommand with-efattributes and the second one is thegrepcommand with thecronattribute. The read side of the pipe is attached to theSTDINof thegrepcommand and the write side is attached to theSTDOUTof thepscommand: the standard output of thepscommand is attached to the standard input of thegrepcommand.Since
psis written to send on the standard output info on each running process, while grep is written to get on its standard input something that has to match a given pattern, you’ll have the answer to your first question:ps -ef;grep cron;pssends data (that even contains the string “grep cron”) togrepgrepmatches its search pattern from theSTDINand it matches the string “grep cron” because of the “cron” attribute you passed in togrep: you are instructinggrepto match the “cron” string and it does because “grep cron” is a string returned bypsat the timegrephas started its execution.When you execute:
the attribute passed instructs
grepto match something containing “c” followed by “ron”. Like the first example, but in this case it will break the match string returned bypsbecause:ps -ef;grep [c]ron;pssends data (that even contains the stringgrep [c]ron) togrepgrepdoes not match its search pattern from the stdin because a string containing “c” followed by “ron” it’s not found, but it has found a string containing “c” followed by “]ron”GNU
grepdoes not have any string matching limit, and on some platforms (I think Solaris, HPUX, aix) the limit of the string is given by the “$COLUMN” variable or by the terminal’s screen width.Hopefully this long response clarifies the shell pipe process a bit.
TIP: