Información del 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)
Desplácese a los EJEMPLOS en la parte inferior si solo quiere profundizar en los ejemplos simplificados que hice.
NOTA: No soy un gran zsh
usuario.
Estaba mirando las fzf
combinaciones de teclas para bash
y zsh
.
Observe cómo ambos ejecutan un comando variable $(__fzfcmd)
. __fzfcmd
de forma predeterminada, envía fzf
a stdout y la sustitución de parámetros solo ejecuta el comando ( fzf
) resultante de la salida.
Una diferencia entre el script bash
y zsh
es que el bash
canaliza aún más la salida $(__fzfcmd)
pero zsh
solo la captura dentro de una matriz. Supongo que se debe a un problema en el zsh
momento en que canaliza aún más la salida de fzf
donde no puede ingresar fzf
y el proceso al que se canaliza fzf
no obtiene ningún stdin. Su única opción es ^Z
o ^C
. ^C
Parece que el proceso de fondo por alguna razón. O tal vez sólo querían que en una matriz para que pudieran podrían ejecutar zle vi-fetch-history
en él . La bash
versión hace algo de magia en la combinación de teclas con"\e^": history-expand-line
Ahora fzf
no es importante. Parece que solo necesita un programa que salga tty
a ser llamado por sustitución de parámetros para causar este problema. Entonces mostraré algunos ejemplos más simples.
Aquí hay algunos otros comandos que se envían al tty
que pueden causar este problema en zsh
:
- vipe (ejecutar editor en medio de una tubería)
'vim -'
(haga que vim lea desde stdin. similar a vipe pero no saldrá a stdout)
En los ejemplos a continuación, reemplace cada aparición de vipe
con vim -
si no desea realizar una instalación por separado. Solo recuerde que vim -
no generará el contenido del editor en stdout como lo vipe
hace.
EJEMPLOS
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
Ahora, me pregunto por qué 2)
tiene un problema zsh
pero no para bash
y por qué 4)
y 5)
soluciona el problema zsh
.
Los requisitos para zsh
que este problema parezca ser exactamente lo que puse en el título:
- tubo de entrada
- comando ejecutado por sustitución de variable / parámetro que tiene
tty
salida - tubo de salida
ACTUALIZAR
He añadido otra solución que no causa zsh
a tener este problema, 5)
. Es similar a, 4)
pero en lugar de redirigir stdout
directamente stin
, lo redirijo a un archivo que redirige al stdin
uso de la sustitución de procesos.
when either a computer program or system ceases to respond to inputs
(echo | $(echo vipe) | cat)
ps
lo dirá la salida de , en ninguno de estos casos las conchas están congeladas o atascadas. Simplemente están esperando los procesos secundarios de la manera normal; y de hecho volverán a solicitar entradas de la manera normal una vez que esos procesos secundarios se suspendan o finalicen. El título y el cuerpo de su pregunta incluyen una premisa falsa implícita. "¿Por qué se congela mi caparazón?" es una pregunta cargada sin respuesta cuando su shell no se congela en primer lugar. Tendría una mejor pregunta para eliminar esta premisa falsa implícita.