Podczas eksperymentów z przekierowaniem wyjścia i podstawieniem procesu natknąłem się na następującą komendę i jej wynik:
me @ elem: ~ $ echo foo>> (cat); pasek echa bar me @ elem: ~ $ foo
(Tak, ta pusta nowa linia na końcu jest celowa).
Więc uderz w pasek echa, wypisuje mój zwykły monit, echo foo, echo jest nową linią i pozostawia tam mój kursor. Jeśli ponownie wcisnę Enter, wydrukuje mój monit w nowym wierszu i pozostawi kursor za nim (zgodnie z oczekiwaniami, gdy ktoś uderzy Enter w pustym wierszu poleceń).
Spodziewałem się, że napisze foo do deskryptora pliku, cat czyta foo i echo, pasek drugiego echa, a następnie wraca do wiersza poleceń. Ale oczywiście tak nie jest.
Czy ktoś mógłby wyjaśnić, co się dzieje?
bash
shell
process-substitution
concurrency
Stanley Yu
źródło
źródło
Odpowiedzi:
Może być
foo
wyświetlany przedbar
, pobar
, a nawet po monicie, w zależności od czasu. Dodaj małe opóźnienie, aby uzyskać spójny czas:bar
pojawia się natychmiast, potemfoo
po jednej sekundzie, a następnie kolejny monit po kolejnej sekundzie.Dzieje się tak, że bash wykonuje podstawienia procesów w tle.
sleep 1; cat
i ustawia do niej potok.echo foo
. Ponieważ nie zapełnia to bufora potoku,echo
polecenie kończy się bez blokowania.echo bar
.sleep 2
.sleep 1
.sleep 1
wraca do podprocesu. Podproces przechodzi do wykonaniacat
.cat
kopiuje dane wejściowe na dane wyjściowe (wyświetlane na ekranie) i zwraca.sleep 2
wraca. Proces powłoki głównej kończy się i pojawia się następny monit.źródło
Nie potrzebujesz substytucji procesu, aby uzyskać ten efekt. Spróbuj tego:
Otrzymasz ten sam wynik (bez
bar
; zostawię to jako ćwiczenie) i z tego samego powodu. W obu przypadkachcat
jest uruchamiany jako zadanie w tle. W mojej linii tutaj jest to jednoznaczne. W przypadku podstawienia procesu jest on również jawny - jest to osobny proces dołączony do deskryptora pliku nazwy - ale być może nie jest tak oczywisty.Proces potomny niekoniecznie kończy się przed
bash
wydrukowaniem następnego monitu. A ponieważ jego dane wyjściowe są buforowane, nic nie wysyła, dopóki się nie zakończy. W tym momencie bash właśnie drukował$
na stderr, a teraz proces w tle kończy się po wydrukowaniufoo
i nowej linii.źródło