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 zsh
usuário.
Eu estava olhando as fzf
combinações de teclas para bash
e zsh
.
Observe como os dois executam um comando variável $(__fzfcmd)
. __fzfcmd
por padrão, gera fzf
para stdout e a substituição de parâmetro apenas executa command ( fzf
) resultante da saída.
Uma diferença entre o script bash
e zsh
é que bash
aquele canaliza ainda mais a saída, $(__fzfcmd)
mas zsh
apenas a captura dentro de uma matriz. Meu palpite é que, devido a um problema, zsh
quando você canaliza ainda mais a saída de fzf
onde não pode entrar fzf
e o processo canalizado por fzf
não recebe nenhum stdin. Sua única opção é ^Z
ou ^C
. ^C
parece 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 bash
versão faz alguma mágica na ligação de chave com"\e^": history-expand-line
Agora fzf
não é importante. Parece que você só precisa de um programa que produza tty
para 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 tty
que 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 vipe
por 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 vipe
faz.
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, zsh
mas não para, bash
e por que 4)
e 5)
corrige o problema zsh
.
Os requisitos para zsh
ter 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
tty
saída - tubo de saída
ATUALIZAR
Eu adicionei outra solução alternativa que não causa zsh
esse problema 5)
,. É semelhante, 4)
mas, em vez de redirecionar stdout
diretamente para stin
, eu o redireciono para um arquivo que redireciona para o stdin
uso da substituição de processo.
ps
dirá, 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.when either a computer program or system ceases to respond to inputs
(echo | $(echo vipe) | cat)
Respostas:
Acredito que seu problema se resume a citar indevidamente suas expansões.
Citando zsh: 14 Expansão
Observe que o Exemplo 2 da sua pergunta resulta em um eco infinito de NULL, devido a:
Em outras palavras, o shell espera infinitamente pelo
echo
, porque o delimitador padrão é ESPAÇO, o eco nunca é concluído. Consulte TLDP: Variáveis internas . Isso deixa um cano pendurado para ocat
comando.Como palpite, acredito que 4 e 5 funcionam devido ao redirecionamento de saída.
fonte