Why does ps o/p list the grep process after the pipe?

前端 未结 7 2390
孤街浪徒
孤街浪徒 2020-12-08 20:50

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         


        
相关标签:
7条回答
  • 2020-12-08 21:02

    You wrote: "From my understanding, ps lists the processes and pipes the list to grep. grep hasn't even started running while ps is listing processes".

    Your understanding is incorrect.

    That is not how a pipeline works. The shell does not run the first command to completion, remember the output of the first command, and then afterwards run the next command using that data as input. No. Instead, both processes execute and their inputs/outputs are connected. As Ben Jackson wrote, there is nothing to particularly guarantee that the processes run at the same time, if they are both very short-lived, and if the kernel can comfortably manage the small amount of data passing through the connection. In that case, it really could happen the way you expect, only by chance. But the conceptual model to keep in mind is that they run in parallel.

    If you want official sources, how about the bash man page:

      A pipeline is a sequence of one or more commands separated by the character |.  The format for a pipeline is:
    
             [time [-p]] [ ! ] command [ | command2 ... ]
    
      The  standard  output  of command is connected via a pipe to the standard input of command2.  This connection is
      performed before any redirections specified by the command (see REDIRECTION below).
    
      ...
    
      Each command in a pipeline is executed as a separate process (i.e., in a subshell).
    

    As for your second question (which is not really related at all, I am sorry to say), you are just describing a feature of how regular expressions work. The regular expression cron matches the string cron. The regular expression [c]ron does not match the string [c]ron. Thus the first grep command will find itself in a process list, but the second one will not.

    0 讨论(0)
  • 2020-12-08 21:05

    pgrep is sometimes better than ps -ef | grep word because it exclude the grep. Try

    pgrep -f bash
    pgrep -lf bash
    
    0 讨论(0)
  • 2020-12-08 21:07

    The shell constructs your pipeline with a series of fork(), pipe() and exec() calls. Depending on the shell any part of it may be constructed first. So grep may already be running before ps even starts. Or, even if ps starts first it will be writing into a 4k kernel pipe buffer and will eventually block (while printing a line of process output) until grep starts up and begins consuming the data in the pipe. In the latter case if ps is able to start and finish before grep even starts you may not see the grep cron in the output. You may have noticed this non-determinism at play already.

    0 讨论(0)
  • 2020-12-08 21:09
    $ ps -ef | grep cron
    

    Linux Shell always execute command from right to left. so, before ps -ef execution grep cron already executed that's why o/p show's the command itself.

    $ ps -ef | grep [c]ron
    

    But in this u specified grep ron followed by only c. so, o/p is without command line because in command there is [c]ron.

    0 讨论(0)
  • 2020-12-08 21:10

    Your actual question has been answered by others, but I'll offer a tip: If you would like to avoid seeing the grep process listed, you can do it this way:

    $ ps -ef | grep [c]ron
    
    0 讨论(0)
  • 2020-12-08 21:13

    In your command

    ps -ef | grep 'cron'
    

    Linux is executing the "grep" command before the ps -ef command. Linux then maps the standard output (STDOUT) of "ps -ef" to the standard input (STDIN) of the grep command.

    It does not execute the ps command, store the result in memory, and them pass it to grep. Think about that, why would it? Imagine if you were piping a hundred gigabytes of data?

    Edit In regards to your second question:

    In grep (and most regular expression engines), you can specify brackets to let it know that you'll accept ANY character in the brackets. So writing [c] means it will accept any charcter, but only c is specified. Similarly, you could do any other combination of characters.

    ps aux | grep cron
    root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron
    root     23744  0.0  0.0  14564   900 pts/0    S+   21:13   0:00 grep --color=auto cron
    

    ^ That matches itself, because your own command contains "cron"

    ps aux | grep [c]ron
    root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron
    

    That matches cron, because cron contains a c, and then "ron". It does not match your request though, because your request is [c]ron

    You can put whatever you want in the brackets, as long as it contains the c:

    ps aux | grep [cbcdefadq]ron
    root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron
    

    If you remove the C, it won't match though, because "cron", starts with a c:

    ps aux | grep [abedf]ron
    

    ^ Has no results

    Edit 2

    To reiterate the point, you can do all sorts of crazy stuff with grep. There's no significance in picking the first character to do this with.

    ps aux | grep [c][ro][ro][n]
    root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron
    
    0 讨论(0)
提交回复
热议问题