comando “read” esperando pela nova linha adicional se a entrada vier através do pipe

3

Se eu simplesmente executar read , ele lê uma linha e sai imediatamente quando o Enter é pressionado.

$ read
typing something here
$

No entanto, quando eu passo a entrada através de um tubo, por ex. de cat , read se comporta de maneira diferente e continua em exibição até encontrar a segunda nova linha:

$ cat | read
typing first line
typing second line
$

Alguém pode explicar por que é assim?

PS: Esta pergunta foi inspirada por Como alimentar entrada padrão e despejar em arquivo ao mesmo tempo?

    
por Byte Commander 02.09.2017 / 00:37

1 resposta

2

Não tem nada a ver com a nova linha.

Se você executar seu comando usando strace , descobrirá que cat receberá um SIGPIPE no final antes de ser fechado:

$ strace cat | read

...
someOutput
...
+++ killed by SIGPIPE +++
  1. O primeiro comando cat é executado.
  2. Então você digita algo pela primeira vez e aperta o Enter .
  3. O que você digitou será canalizado para o read .
  4. cat ainda está em execução e aguardando um EOF.
  5. Você digita outra coisa e, em seguida, pressiona o Enter agian.
  6. Desta vez, não é possível canalizar para read , porque não há mais read esperando pela entrada (ela foi fechada após o primeiro canal), a menos que você a execute assim:

    cat | while read line; do echo $line; done;
    
  7. cat receberá um SIGPIPE e será fechado.
  

Um processo recebe um SIGPIPE quando tenta gravar em um pipe (chamado ou não) ou no soquete do tipo SOCK_STREAM que não possui mais nenhum leitor. [1]

Receber SIGPIPE acontece depois quando o segundo pipe acontece.

Por exemplo, considere o comando yes , porque um comando como yes canaliza algo rápido e repetidamente:

yes | read

ele é fechado imediatamente após o segundo canal, preste atenção nas duas write() chamadas:

close(3)                                = 0                    
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192          
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = -1 EPIPE (Broken pipe) 
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=3542, si_uid=1000} ---
+++ killed by SIGPIPE +++

Embora o comando yes seja muito rápido, você pode ver mais de duas chamadas write() , no entanto, se você executá-lo várias vezes, verá pelo menos duas chamadas e nunca uma.

    
por Ravexina 02.09.2017 / 01:18