Informacja o systemie:
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)
Przewiń do PRZYKŁADÓW u dołu, jeśli chcesz po prostu zagłębić się w uproszczone przykłady, które stworzyłem.
UWAGA: Nie jestem dużym zsh
użytkownikiem.
Szukałem na fzf
skróty klawiszowe dla bash
i zsh
.
Zwróć uwagę, jak oba uruchamiają zmienne polecenie $(__fzfcmd)
. __fzfcmd
domyślnie wyświetla fzf
wyjście na standardowe wyjście, a podstawienie parametru po prostu uruchamia polecenie ( fzf
) wynikające z wyjścia.
Jedną różnicą między skryptem bash
i zsh
jest to, że ta bash
kolejna potokuje wyjście, $(__fzfcmd)
ale zsh
tylko przechwytuje je w tablicy. Domyślam się, że jest to spowodowane problemem, zsh
kiedy dalej potokujesz wyjście fzf
tam, gdzie nie możesz wejść, fzf
a proces przekazywany do fzf
nie dostaje żadnego standardowego wejścia. Twoim jedynym wyborem jest ^Z
lub ^C
. ^C
z jakiegoś powodu wydaje się stanowić tło procesu. A może po prostu chcieli go w tablicy, aby mogli na nim biegaćzle vi-fetch-history
. bash
Wersja robi jakaś magia w kluczu wiązania z"\e^": history-expand-line
Teraz fzf
nie jest ważne. Wygląda na to, że potrzebujesz tylko programu, który wyświetla polecenie tty
wywołania przez podstawienie parametru, aby spowodować ten problem. Pokażę więc kilka prostszych przykładów.
Oto kilka innych poleceń wysyłanych do tych, tty
które mogą powodować ten problem zsh
:
- vipe (uruchom edytor na środku potoku)
'vim -'
(spraw, aby vim czytał ze standardowego wejścia. podobny do vipe, ale nie wyświetli na standardowe wyjście)
W poniższych przykładach zastąpić wszystkie wystąpienia vipe
ze vim -
jeśli nie chcesz zrobić oddzielny zainstalować. Pamiętaj tylko, że vim -
nie wypisze zawartości edytora na standardowe wyjście, tak jak vipe
robi.
PRZYKŁADY:
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
Teraz głównie zastanawiam się, dlaczego 2)
ma problem z, zsh
ale nie z powodu, bash
i dlaczego 4)
i 5)
rozwiązuje problem zsh
.
Wymagania, zsh
aby ten problem wydawał się być dokładnie tym, co podałem w tytule:
- rura wejściowa
- polecenie uruchamiane przez podstawienie zmiennej / parametru, które ma
tty
dane wyjściowe - rura wyjściowa
AKTUALIZACJA
I dodaje inny obejście, które nie powoduje zsh
mieć tego problemu 5)
. Jest podobny do, 4)
ale zamiast przekierowywać stdout
bezpośrednio do stin
, przekierowuję go do pliku, który przekierowuje na stdin
stosowanie substytucji procesu.
when either a computer program or system ceases to respond to inputs
(echo | $(echo vipe) | cat)
ps
, w żadnym z tych przypadków pociski nie są zamrożone lub zablokowane. Po prostu czekają na procesy potomne w normalny sposób; i rzeczywiście powrócą do monitowania o wprowadzenie danych w normalny sposób, gdy te procesy potomne zostaną zawieszone lub zakończone. Tytuł i treść pytania zawierają domyślną fałszywą przesłankę. „Dlaczego moja skorupa się zawiesza?” to pytanie, na które nie można odpowiedzieć, gdy twoja skorupa w ogóle się nie zawiesza. Lepiej byłoby usunąć to ukryte fałszywe założenie.