O wiele łatwiej jest wizualizować rzeczy, jeśli myślisz o tym, co naprawdę dzieje się z „przekierowaniami” i „potokami”. Przekierowania i potoki w bash robią jedną rzecz: modyfikują tam, gdzie wskazują deskryptory plików procesowych 0, 1 i 2 (patrz / proc / [pid] / fd / *).
Gdy rura lub „|” operator jest obecny w wierszu poleceń, pierwszą rzeczą, która się wydarzy, jest to, że bash tworzy FIFO i wskazuje FD 1 komendy po lewej stronie na FO 0 i wskazuje FD 0 komendy po prawej stronie na tę samą FIFO.
Następnie operatory przekierowania dla każdej strony są oceniane od lewej do prawej , a bieżące ustawienia są używane za każdym razem, gdy występuje duplikacja deskryptora. Jest to ważne, ponieważ odkąd rura została skonfigurowana jako pierwsza, FD1 (lewa strona) i FD0 (prawa strona) zostały już zmienione w stosunku do tego, czym normalnie mogły być, a ich powielanie odzwierciedla ten fakt.
Dlatego po wpisaniu czegoś takiego:
command 2>&1 >/dev/null | grep 'something'
Oto, co się dzieje, w kolejności:
- tworzony jest potok (fifo). „polecenie FD1” jest wskazane na tej rurze. „grep FD0” również wskazuje na tę rurę
- „polecenie FD2” jest wskazywane tam, gdzie „polecenie FD1” obecnie wskazuje (potok)
- „polecenie FD1” wskazuje na / dev / null
Zatem wszystkie dane wyjściowe, które „polecenie” zapisuje na FD 2 (stderr), trafiają do potoku i są odczytywane przez „grep” po drugiej stronie. Wszystkie dane wyjściowe, które „komenda” zapisuje na FD 1 (stdout), trafiają do / dev / null.
Jeśli zamiast tego uruchom następujące polecenie:
command >/dev/null 2>&1 | grep 'something'
Oto co się dzieje:
- tworzona jest rura i są do niej wskazywane „polecenie FD 1” i „grep FD 0”
- „polecenie FD 1” wskazuje na / dev / null
- „polecenie FD 2” wskazuje miejsce, w którym obecnie wskazuje FD 1 (/ dev / null)
Zatem wszystkie stdout i stderr z „polecenia” idą do / dev / null. Nic nie trafia do potoku, dlatego „grep” zostanie zamknięty bez wyświetlania czegokolwiek na ekranie.
Zauważ też, że przekierowania (deskryptory plików) mogą być tylko do odczytu (<), tylko do zapisu (>) lub do odczytu-zapisu (<>).
Ostatnia uwaga. To, czy program napisze coś do FD1 lub FD2, zależy wyłącznie od programisty. Dobra praktyka programowania nakazuje, aby komunikaty o błędach trafiały do FD 2, a normalne wyjście do FD 1, ale często można znaleźć niechlujne programowanie, które łączy oba lub w inny sposób ignoruje konwencję.