No zsh, diferença entre cat <(cat) vs cat | gato vs gato = (gato)?

18

Eu esperava cat <(cat)e cat | catfiz o mesmo: copiar linhas de stdin para stdout. Meu entendimento era que ambos executariam a catem um subshell, redirecionariam o catstdout do subshell para um pipe nomeado temporário e, em seguida, executariam outro catno shell atual com o stdin redirecionado para o pipe.

Em vez disso, cat <(cat)permita-me digitar no meu terminal, mas nenhuma das linhas de entrada é copiada e ^Dfalha ao sinalizar EOF; cat | catfunciona como esperado.

Como experimento adicional, verifiquei se cat =(cat)há dificuldades semelhantes cat <(cat), mas funciona como eu esperava: todo o stdin até a ^Dé copiado para stdout de uma só vez.

Alguém pode me ajudar a entender o que o zsh está fazendo sob o capô?

Alan O'Donnell
fonte

Respostas:

23
  1. a | bLigações STDOUTde ae STDINde bapenas usando dup/dup2. Ambos os comandos são executados em paralelo.

  2. a =(b)substitui o argumento apor um nome de arquivo temporário. bserá executado antes, apois o arquivo temporário precisa ser criado antes de poder ser passado paraa

  3. a <(b)substitui o argumento apor um pipe nomeado. ae bcorra em paralelo. Agora é aqui que fica um pouco complicado:

    bestá em segundo plano e não pode ler no terminal. Você pode testá-lo usando strace -p $PIDpara anexar ao seu segundo processo de gato para ver o processo.

    aenquanto isso, tenta ler a partir do pipe nomeado, mas não consegue ler nada como bnão pode ler.

    • Isso significa que você basicamente tem um impasse no qual atenta ler, bmas bnão pode ler STDINe não pode escrever paraa

Mais informações sobre o processo em segundo plano e o terminal do man bash :

Para facilitar a implementação da interface do usuário para o controle de tarefas, o sistema operacional mantém a noção de um ID do grupo de processos do terminal atual . Os membros desse grupo de processos (processos cujo ID do grupo de processos é igual ao atual ID do grupo de processos do terminal) recebem sinais gerados pelo teclado, como o SIGINT . Diz-se que esses processos estão em primeiro plano . fundoprocessos são aqueles cujo ID do grupo de processos difere do terminal; esses processos são imunes aos sinais gerados pelo teclado. Somente processos em primeiro plano têm permissão para ler ou, se o usuário especificar com stty tostop, gravar no terminal. Os processos em segundo plano que tentam ler (gravar para quando stty tostop está em efeito) recebem um sinal SIGTTIN (SIGTTOU) pelo driver de terminal do kernel, que, a menos que seja capturado, suspende o processo.

Ulrich Dangel
fonte
Ótimo, obrigado - isso esclareceu muito!
27712 Alan O'Donnell
11
Observe que, quando não é interativo, o zsh redireciona a entrada padrão dos comandos em segundo plano (incluindo aqueles em <(cmd)) para /dev/null, portanto o comportamento difere ( zsh -c 'cat <(cat)'retorna imediatamente e não gera nada).
Stéphane Chazelas