Informazioni di 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)
Scorri fino agli ESEMPI in basso se vuoi solo approfondire gli esempi semplificati che ho fatto.
NOTA: non sono un grande zsh
utente.
Stavo guardando le fzf
combinazioni di tasti per bash
e zsh
.
Notare come entrambi eseguono un comando variabile $(__fzfcmd)
. __fzfcmd
per impostazione predefinita output fzf
su stdout e la sostituzione dei parametri esegue semplicemente command ( fzf
) risultante dall'output.
Una differenza tra lo script bash
e zsh
è che bash
quello convoglia ulteriormente l'output di $(__fzfcmd)
ma zsh
lo cattura semplicemente all'interno di un array. La mia ipotesi è dovuta a un problema in zsh
cui si esegue ulteriormente il piping dell'output in fzf
cui non è possibile immettere fzf
e il processo a cui viene eseguito il piping fzf
non ottiene alcuno stdin. La tua unica scelta è di ^Z
o ^C
. ^C
sembra fare da sfondo al processo per qualche motivo. O forse volevano solo in una matrice in modo che potessero potessero funzionare zle vi-fetch-history
su di esso . La bash
versione fa un po 'di magia nel key binding con"\e^": history-expand-line
Adesso fzf
non è importante. Sembra che tu abbia solo bisogno di un programma che emetta l'output tty
per essere chiamato dalla sostituzione dei parametri per causare questo problema. Quindi mostrerò alcuni esempi più semplici.
Ecco alcuni altri comandi che tty
generano in output che possono causare questo problema in zsh
:
- vipe (esegui l'editor nel mezzo di una pipe)
'vim -'
(fai in modo che vim legga da stdin. simile a vipe ma non verrà riprodotto in stdout)
Negli esempi seguenti, sostituire ogni occorrenza di vipe
con vim -
se non si desidera eseguire un'installazione separata. Ricorda solo che vim -
il contenuto dell'editor non verrà riprodotto su stdout come vipe
fa.
ESEMPI:
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
Ora, mi chiedo principalmente perché 2)
abbia un problema per zsh
ma non per bash
e perché 4)
e 5)
risolva il problema per zsh
.
I requisiti per zsh
avere questo problema sembrano essere esattamente ciò che ho inserito nel titolo:
- tubo di ingresso
- comando eseguito dalla sostituzione variabile / parametro che ha
tty
generato - tubo di uscita
AGGIORNARE
Ho aggiunto un'altra soluzione che non causare zsh
ad avere questo problema, 5)
. È simile 4)
ma invece di reindirizzare stdout
direttamente in stin
, lo reindirizzo in un file che reindirizza stdin
all'utilizzo della sostituzione del processo.
when either a computer program or system ceases to respond to inputs
(echo | $(echo vipe) | cat)
ps
ti dirà, in nessuno di questi casi i gusci sono congelati o bloccati. Stanno semplicemente aspettando i processi figlio in modo normale; e torneranno sicuramente a richiedere input nel modo normale una volta che quei processi figlio sono sospesi o chiusi. Il titolo e il corpo della domanda includono una premessa implicita falsa. "Perché la mia shell si blocca?" è una domanda caricata senza risposta quando la shell non si blocca in primo luogo. Avresti una domanda migliore per rimuovere questa premessa implicita falsa.