grep invadindo meu ps [duplicado]

5

Quando estou verificando algum processo, geralmente escrevo

ps aux | grep myprocess

E às vezes recebo a saída

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

se o processo não estiver em execução.

Agora eu realmente me pergunto por que o grep está na lista de processos se ele filtra a saída do comando ps depois que ps foi executado?

    
por Eimantas 31.12.2014 / 06:49

6 respostas

12

Esse comportamento é totalmente normal, devido a como o bash gerencia o uso do pipe.

O

pipe é implementado pelo bash usando o pipe syscall. Depois dessa chamada, o bash bifurca e substitui a entrada padrão ( descritor de arquivo 0 ) com a entrada do processo correto ( grep ). O processo bash principal cria outro fork e passa o descritor de saída do fifo no lugar da entrada padrão ( file description 1 ) e lança o comando esquerdo.

O utilitário ps é iniciado após o comando grep , para que você possa vê-lo na saída.

Se você não estiver convencido, use set -x para ativar o rastreamento de comandos. Por exemplo:

+ 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

Para mais explicações, você pode verificar essa parte do shell básico c: link

    
por 31.12.2014 / 09:33
8

Quando estou interessado apenas na presença de um processo, uso pgrep , que não mostra esse comportamento, por exemplo:

$ pgrep myprocess
1900

Em outros casos (quando estou interessado em mais informações), geralmente adiciono um | grep -v grep para descartar as linhas grep, por exemplo:

$ ps -ef | grep myprocess| grep -v grep
    
por 31.12.2014 / 09:58
6

O pipe não se comporta como ; . Começa ambos os processos juntos. É por isso que o comando grep também apareceu. Então, quando você deu ps aux | grep myprocess , o ps aux incluiu o grep myprocess , então o grep incluiu isso em sua saída.

Para verificar isso, eu dei dois comandos dd no meu servidor de teste assim:

[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

E quando eu verifiquei o processo dd , ele mostra que ambos começaram ao mesmo tempo (veja a coluna que diz que 2:55 minutos se passaram):

[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 ~]$

Agora, se você quiser excluir o grep de ser gerado, use regex. Isso excluirá o grep do resultado:

ps aux | grep "[m]yprocess"

Por exemplo, se você estiver procurando por um processo httpd, use:

ps aux | grep "[h]ttpd"

Mas sugiro que você use pgrep -a , que será mais confiável.

[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 ~]$
    
por 31.12.2014 / 07:24
3

Você está correto, não é assim que funciona. O shell não espera que o primeiro processo em um pipeline saia antes de iniciar o próximo. Começa todos eles. Dessa forma, o ps pode ver o grep em execução.

    
por 31.12.2014 / 06:58
2

Considere este experimento mental: se ps foi executado antes de invocar grep como você acha que deveria, isso significaria que o shell precisaria:

  1. Invoque ps .
  2. Buffer toda a sua saída (porque não tem mais para onde ir ainda).
  3. Invoque grep .
  4. Alimente a saída salva com grep ' stdin .

Isso é um desperdício; é um uso mais eficiente da memória para invocar grep primeiro, espere pela entrada e, em seguida, alimente ps stdout diretamente para grep ' stdin .

Ou, levado ao extremo, considere o caso de canalizar a saída de um programa que gera uma quantidade infinita de saída, por exemplo:

$ yes | less

Se o shell executasse yes antes de less , você ficaria esperando para sempre (ou até esgotar completamente a memória do seu computador).

    
por 31.12.2014 / 20:06
1

Apenas confirmando como BowlOfRed e alexises declararam. Aqui está uma representação visual do canal ps e grep de volta para ps novamente para mostrar como os processos canalizados são executados. Observe que o% final ps x --forest está ignorando a entrada, mas mantém os processos previamente canalizados ativos para que eles sejam exibidos.

ps -ef | grep myprocess | ps x --forest

Trecho de saída:

25056 pts/3    Ss     0:05  \_ bash
12243 pts/3    R+     0:00  |   \_ ps -ef
12244 pts/3    S+     0:00  |   \_ grep --color=auto myprocess
12245 pts/3    R+     0:00  |   \_ ps x --forest

Observe que o bash está no estado de suspensão interrompível S (aguardando a conclusão de um evento). O s indica que é o líder da sessão, como você verá abaixo.

Com a opção -ef , você também pode ver que os processos filhos estão sendo executados com o mesmo ID pai, que é o ID do processo de bash , 25056 .

ps x | grep myprocess | ps -ef --forest

Trecho de saída:

UID         PID   PPID   C STIME TTY          TIME  CMD
iamuser     25056 16737  0 Dec23 pts/3    00:00:05  \_ bash
iamuser     12161 25056  0 05:02 pts/3    00:00:00  |   \_ ps x
iamuser     12162 25056  0 05:02 pts/3    00:00:00  |   \_ grep myprocess
iamuser     12163 25056  0 05:02 pts/3    00:00:00  |   \_ ps -ef --forest
    
por 31.12.2014 / 12:24