Como o bash trata ">> ()"

9

Ao experimentar o redirecionamento de saída e a substituição de processos, deparei-me com o seguinte comando e sua saída resultante:

    me @ elem: ~ $ echo foo>> (gato); barra de eco
    Barra
    me @ elem: ~ $ foo

(Sim, essa nova linha vazia no final é intencional.)

Então a barra do eco do bash, imprime meu prompt habitual, o eco do eco, o eco é uma nova linha e deixa meu cursor lá. Se eu pressionar enter novamente, ele imprimirá meu prompt em uma nova linha e deixará o cursor seguindo (como esperado quando alguém pressiona enter em uma linha de comando vazia).

Eu esperava que ele escrevesse foo em um descritor de arquivo, cat o lê e echo foo, a segunda barra de eco de eco e, em seguida, volta ao prompt de comando. Mas esse claramente não é o caso.

Alguém poderia explicar o que está acontecendo?

Stanley Yu
fonte
Gostaria de sugerir que você procure as respostas sobre isso: unix.stackexchange.com/questions/182800/… Explica o redirecionamento duplo e explica por que você está terminando com resultados diferentes. Muru e Michael Hormers.
No Time
Para uma pergunta que explique explicitamente por que a saída da substituição do processo aparece após o prompt (e, em algumas circunstâncias, não aparece) em algumas versões do shell Bourne Again, consulte unix.stackexchange.com/questions/471987 .
JdeBP # 28/18

Respostas:

9

Você pode ver fooexibido antes bar, depois barou mesmo após o prompt, dependendo do tempo. Adicione um pequeno atraso para obter um tempo consistente:

$ echo foo > >(sleep 1; cat); echo bar; sleep 2 
bar
foo
$

baraparece imediatamente, foodepois de um segundo e o próximo prompt após outro segundo.

O que está acontecendo é que o bash executa substituições de processos em segundo plano.

  1. O processo principal do bash inicia um subshell para executar sleep 1; cate configura um pipe para ele.
  2. O processo principal do bash é executado echo foo. Como isso não preenche o buffer do canal, o echocomando termina sem bloquear.
  3. O processo principal do bash é executado echo bar.
  4. O processo principal do bash inicia o comando sleep 2.
  5. Enquanto isso, o subshell está lançando o comando sleep 1.
  6. Após cerca de 1 segundo, sleep 1retorna no subprocesso. O subprocesso continua executando cat.
  7. cat copia sua entrada para sua saída (que é exibida na tela) e retorna.
  8. O subshell terminou seu trabalho, ele sai.
  9. Depois de mais um segundo, sleep 2retorna. O processo principal do shell termina a execução e você vê o próximo prompt.
Gilles 'SO- parar de ser mau'
fonte
3

Você não precisa de substituição de processo para obter esse efeito. Tente o seguinte:

( echo foo | cat & )

Você obterá o mesmo resultado (sem o bar; deixarei isso como um exercício) e pelo mesmo motivo. Nos dois casos, caté iniciado como uma tarefa em segundo plano. Na minha linha aqui, isso é explícito. No caso de substituição de processo, também é explícito - é um processo separado anexado a um descritor de arquivo de nome - mas talvez não seja tão óbvio.

O processo filho não termina necessariamente antes de bashimprimir o próximo prompt. E, como sua saída é armazenada em buffer, ela não produz nada até terminar. Nesse ponto, o bash acabou de ser impresso $no stderr e agora o processo em segundo plano sai após a impressão fooe uma nova linha.

rici
fonte