Informação do sistema:
macOS Sierra 10.12.6
zsh 5.4.2 (x86_64-apple-darwin16.7.0)
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)
Role para os EXEMPLOS na parte inferior, se você quiser apenas explorar os exemplos simplificados que fiz.
NOTA: Eu não sou um grande zshusuário.
Eu estava olhando as fzfcombinações de teclas para bashe zsh.
Observe como os dois executam um comando variável $(__fzfcmd). __fzfcmdpor padrão, gera fzfpara stdout e a substituição de parâmetro apenas executa command ( fzf) resultante da saída.
Uma diferença entre o script bashe zshé que bashaquele canaliza ainda mais a saída, $(__fzfcmd)mas zshapenas a captura dentro de uma matriz. Meu palpite é que, devido a um problema, zshquando você canaliza ainda mais a saída de fzfonde não pode entrar fzfe o processo canalizado por fzfnão recebe nenhum stdin. Sua única opção é ^Zou ^C. ^Cparece embasar o processo por algum motivo. Ou talvez eles apenas o quisessem em uma matriz para que pudessem executá zle vi-fetch-history-lo . A bashversão faz alguma mágica na ligação de chave com"\e^": history-expand-line
Agora fzfnão é importante. Parece que você só precisa de um programa que produza ttypara ser chamado por substituição de parâmetro para causar esse problema. Então, mostrarei alguns exemplos mais simples.
Aqui estão alguns outros comandos ttyque podem causar esse problema em zsh:
- vipe (execute o editor no meio de um cano)
'vim -'(faça com que o vim seja lido do stdin. semelhante ao vipe, mas não será exibido como stdout)
Nos exemplos abaixo, substitua cada ocorrência de vipepor vim -se você não quiser fazer uma instalação separada. Lembre-se de que vim -não produzirá o conteúdo do editor para o stdout, como vipefaz.
EXEMPLOS:
1) echo 1 | vipe | cat # works in both bash and zsh
2) echo 1 | $(echo vipe) | cat # works in bash only. zsh problem with no output until I hit `^C`:
^C
zsh: done echo 1 |
zsh: suspended (tty output) $(echo vipe) |
zsh: interrupt cat
# seems like the process is backgrounded. I can still see it in jobs command
3) cat <(echo 1 | $(echo vipe)) # zsh and bash has the problem. I'm guessing because
# the file isn't finished writing and cat is
# blocking vipe's tty output
# both their `^C` output is just:
^C # nothing special, as expected
4) cat < <(echo 1 | $(echo vipe)) # works in both bash and zsh
5) echo 1 | $(echo vipe) > >(cat) # works in both bash and zsh
# The following don't have and input pipe to vipe.
# Type something then send EOF with ^D
6) vipe | cat # works for both
7) $(echo vipe) | cat # works for both
Agora, estou me perguntando principalmente por que 2)há um problema para, zshmas não para, bashe por que 4)e 5)corrige o problema zsh.
Os requisitos para zshter esse problema parecem ser exatamente o que eu coloquei no título:
- tubo de entrada
- comando executado pela substituição de variável / parâmetro que possui
ttysaída - tubo de saída
ATUALIZAR
Eu adicionei outra solução alternativa que não causa zshesse problema 5),. É semelhante, 4)mas, em vez de redirecionar stdoutdiretamente para stin, eu o redireciono para um arquivo que redireciona para o stdinuso da substituição de processo.
when either a computer program or system ceases to respond to inputs
(echo | $(echo vipe) | cat)
psdirá, em nenhum desses casos as conchas estão congeladas ou presas. Eles estão simplesmente aguardando processos filhos da maneira normal; e, de fato, voltarão a solicitar a entrada da maneira normal assim que os processos filhos forem suspensos ou encerrados. O título e o corpo da sua pergunta incluem uma premissa implícita e falsa. "Por que minha concha congela?" é uma pergunta carregada sem resposta quando seu shell não está realmente congelando em primeiro lugar. Você teria uma pergunta melhor para remover essa premissa falsa implícita.