W jakiej kolejności działają polecenia potokowe?


89

Nigdy tak naprawdę nie myślałem o tym, jak powłoka faktycznie wykonuje polecenia potokowe. Zawsze mówiono mi, że „standardowe wyjście jednego programu jest przesyłane do wejścia innego standardowego”, jako sposób myślenia o rurach. Więc naturalnie pomyślałem, że w przypadku powiedzmy A | B, A uruchamia się jako pierwsze, a następnie B pobiera standardowe wyjście A i używa standardowego wejścia A jako wejścia.

Zauważyłem jednak, że kiedy ludzie szukają określonego procesu w ps, dołączają grep -v „grep” na końcu polecenia, aby upewnić się, że grep nie pojawia się w końcowym wyniku. Oznacza to, że w poleceniu ps aux | grep "bash" | grep -v "grep", co oznacza, że ​​ps wiedział, że grep jest uruchomiony i dlatego jest w wyniku ps. Ale jeśli ps zakończy działanie, zanim jego dane wyjściowe zostaną przekazane do grep, to skąd wiedział, że grep działa?

flamingtoast@FTOAST-UBUNTU: ~$ ps | grep ".*"
PID TTY          TIME CMD
3773 pts/0    00:00:00 bash
3784 pts/0    00:00:00 ps
3785 pts/0    00:00:00 grep

dlaczego nie zaakceptować odpowiedzi?
törzsmókus

Odpowiedzi:


64

Polecenia potokowe są uruchamiane jednocześnie. Kiedy biegniesz ps | grep …, to szczęście losowania (lub kwestia szczegółów działania powłoki w połączeniu z dopracowaniem harmonogramu głęboko w trzewiach jądra) co do tego, psczy grepzaczyna się najpierw, a w każdym razie nadal wykonać jednocześnie.

Jest to bardzo często używane, aby umożliwić drugiemu programowi przetwarzanie danych wychodzących z pierwszego programu, zanim pierwszy program zakończy działanie. Na przykład

grep pattern very-large-file | tr a-z A-Z

zaczyna wyświetlać pasujące linie dużymi literami, nawet zanim grepzakończy przeglądanie dużego pliku.

grep pattern very-large-file | head -n 1

wyświetla pierwszą pasującą linię i może przestać przetwarzać na długo przed grepzakończeniem odczytu pliku wejściowego.

Jeśli czytasz gdzieś, że programy potokowe działają w sekwencji, uciekaj od tego dokumentu. Programy potokowe działają jednocześnie i zawsze mają.


7
I fajne w tym przykładzie jest to, że gdy głowa dostaje jedną linię, której potrzebuje, kończy się, a gdy grep to zauważy, kończy się również bez wykonywania dodatkowej pracy za darmo.
Joe

Wydaje mi się, że istnieje jakiś bufor IO dotyczący potoku ... skąd mam wiedzieć, że ma rozmiar w bajtach? Co chcę przeczytać, aby dowiedzieć się więcej na ten temat? :)
n611x007

3
@naxa Właściwie istnieją dwa bufory. W programie znajduje się bufor stdiogrep , a bufor jest zarządzany przez jądro w samym potoku. W przypadku tego drugiego zobacz Jak duży jest bufor bufora?
Gilles

49

Kolejność uruchamiania poleceń nie ma znaczenia i nie jest gwarantowana. Nie wdając się w szczegóły wtajemniczeń pipe(), fork(), dup()i execve(), powłoki najpierw tworzy rurę, przewód dla danych, które będą przepływać pomiędzy procesami, a następnie tworzy procesy z końcami rury połączonej z nimi. Pierwszy uruchomiony proces może blokować oczekiwanie na dane wejściowe z drugiego procesu lub blokować oczekiwanie na rozpoczęcie przez drugi proces odczytu danych z potoku. Te oczekiwania mogą być dowolnie długie i nie mają znaczenia. Bez względu na kolejność uruchamiania procesów dane są ostatecznie przesyłane i wszystko działa.


5
Dobra odpowiedź, ale OP wydaje się sądzić, że procesy przebiegają sekwencyjnie. Możesz tu wyjaśnić, że procesy są uruchamiane jednocześnie, a rura jest jak ... rura między wiadrami, w której woda przepływa przez cały czas (w przybliżeniu).
Keith

Dziękuję za wyjaśnienie. Źródła, które czytałem, sprawiały wrażenie, jakby programy potokowe były uruchamiane sekwencyjnie, a nie jednocześnie.
action_potato

Aby zobaczyć proces rozpoczynający się w nieokreślony sposób, spróbuj uruchomić to 1000 razy: echo -na> & 2 | echo b> i 2
Ole Tange

28

Wydaje się, że istnieje ryzyko, że zostanie pokonany martwy koń

    A | b

jest równa

    > Temporary_file 
    B < temporary_file 
    rm temporary_file

Ale kiedy powstał Unix i dzieci jeździły do ​​szkoły dinozaury, dyski były bardzo małe i często dość łagodne polecenie zajmowało całą wolną przestrzeń w systemie plików. Gdyby Bbyło coś takiego , końcowy wynik potoku mógłby być znacznie mniejszy niż ten plik pośredni. Dlatego też, rura została rozwinięta, a nie jako skrótowy zapis „run pierwszy, a następnie uruchomić B przy udziale A jest wyjściowy” modelu, a jako sposób , aby wykonać równocześnie z i eliminują potrzebę przechowywania plików pośrednią na dysku.grep some_very_obscure_stringBA


2
To odpowiada dlaczego i dlatego otrzymuję mój głos.
LIttle Ancient Forest Kami

1

Zazwyczaj uruchamiasz to w bash. proces działa i uruchamia się jednocześnie, ale działa równolegle przez powłokę. Jak to jest możliwe?

  1. jeśli nie jest to ostatnie polecenie w potoku, utwórz potok bez nazwy z parą gniazd
  2. widelec
  3. w potomku przypisz stdin / stdout do gniazd, jeśli jest to potrzebne (dla pierwszego procesu w potoku stdin nie jest ponownie przypisany, to samo dla ostatniego procesu i jego standardu)
  4. w podrzędnym EXEC podano polecenie z argumentami, które usuwają oryginalny kod powłoki, ale pozostawiają wszystkie otwarte gniazda. Identyfikator procesu potomnego nie zostanie zmieniony, ponieważ jest to ten sam proces potomny
  5. jednocześnie z dzieckiem, ale równolegle pod główną powłoką, przejdź do kroku 1.

system nie gwarantuje, jak szybko zostanie wykonane exec i rozpocznie się uruchamianie określonej komendy. jest niezależny od powłoki, ale system. To dlatego, że:

ps auxww| grep ps | cat

raz pokaż grepi / lub pspolecenie, a następnie teraz. Zależy to od tego, jak szybko jądro naprawdę uruchomi procesy przy użyciu funkcji exec systemu.


1
Równoczesne wykonywanie oznacza, że ​​dwa lub więcej procesów wykonuje się w tym samym przedziale czasowym, zwykle z pewną zależnością między nimi. Równoległe wykonywanie oznacza, że ​​dwa lub więcej procesów wykonuje się jednocześnie (np. Na osobnych rdzeniach procesora w tym samym czasie). Równoległość nie jest istotna dla pytania, ani nie jest wykonywane „jak szybko” exec(), ale jak przeplataneexec() są wywołania i wykonywanie programów w potoku .
Thomas Nyman
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.