Patrząc na dwa polecenia osobno:
utility 2>&1 >output.log
Ponieważ przekierowania są przetwarzane od lewej do prawej, standardowy strumień błędów byłby najpierw przekierowywany do dowolnego miejsca, w którym idzie standardowy strumień wyjściowy (ewentualnie do konsoli), a następnie standardowy strumień wyjściowy byłby przekierowywany do pliku. Standardowy strumień błędów nie zostałby przekierowany do tego pliku.
Widocznym efektem tego jest to, że otrzymujesz to, co jest generowane przy standardowym błędzie na ekranie, i to, co jest wytwarzane przy standardowym wyjściu w pliku.
utility 2>&1 | tee output.log
Tutaj przekierowujesz standardowy błąd w to samo miejsce, co standardowy strumień wyjściowy. Oznacza to, że oba strumienie będą przesyłane do tee
narzędzia jako pojedynczy, przeplatany strumień wyjściowy, i że te standardowe dane wyjściowe zostaną zapisane w danym pliku przez tee
. Dane byłyby dodatkowo odtwarzane przez tee
konsolę (w ten tee
sposób duplikuje strumienie danych).
To, które z nich zostanie użyte, zależy od tego, co chcesz osiągnąć.
Zauważ, że nie byłbyś w stanie odtworzyć efektu drugiego potoku tylko za pomocą >
(jak w utility >output.log 2>&1
, co zapisałoby zarówno standardowe wyjście, jak i błąd w pliku). Musisz użyć, tee
aby uzyskać dane w konsoli, a także w pliku wyjściowym.
Dodatkowe uwagi:
The Widoczny efekt pierwszego polecenia
utility 2>&1 >output.log
byłby taki sam jak
utility >output.log
To znaczy, standardowe wyjście trafia do pliku, a standardowy błąd trafia do konsoli.
Gdyby na końcu każdego z powyższych poleceń dodano kolejny krok przetwarzania, istniałaby duża różnica:
utility 2>&1 >output.log | more_stuff
utility >output.log | more_stuff
W pierwszym potoku more_stuff
uzyskałby to, co pierwotnie jest standardowym strumieniem błędów, utility
jako swoje standardowe dane wejściowe, natomiast w drugim potoku, ponieważ jest to tylko wynikowy standardowy strumień wyjściowy, który jest kiedykolwiek wysyłany przez potok, more_stuff
część potoku nie otrzyma nic czytać na jego standardowym wejściu.
utility 2>&1 | tee output.log
masz na myśli, że ponieważ 1 jest kierowane do tee, również 2. 2. Ponieważ tee duplikuje strumień, dane wyjściowe są wyświetlane zarówno na konsoli, jak i zapisywane do pliku? Stąd różnica międzyutility 2>&1 > output.log
iutility 2>&1 | tee output.log
polegatee
na tym, że powiela strumień. Czy to prawda?utility 2>&1 > output.log | more_stuff
iutility >ouput.log
| more_stuff, is the difference that
more_stuff` ma standardowe wyjście błędów do konsoli jako dane wejściowemore_stuff
? Ponieważ w drugim przykładzie konsola nie ma danych wyjściowych, zasadniczo nie ma danych wejściowych domore_stuff
? Jeśli tak, nie jest to jasne, ponieważ w poprzednim akapicie zauważasz, że standardowe wyjście trafia do pliku, a standardowy błąd do konsoli.more_stuff
otrzyma to, coutility
pierwotnie wysłano do jego strumienia błędów (ale które zostało przekierowane na standardowe wyjście). Nie dlatego, że trafiłby na konsolę, gdybymore_stuff
go nie było, ale dlatego, że przechodzi do standardowego strumienia wyjściowego . W drugim poleceniu nic niemore_stuff
otrzymuje, ponieważ nie ma standardowego wyjścia z lewej strony potoku. Strumień błędów z nadal trafiałby do konsoli w drugim poleceniu.utility
utility > output.log | more_stuff
nie powoduje wyjścia w standardowym strumieniu wyjściowym ze standardowego punktu widzenia błędu?Nota redakcyjna
Przeczytaj komentarze do tej odpowiedzi - derobert .
Oryginalna odpowiedź
2>&1 >output.log
oznacza, że najpierw zacznij wysyłać wszystkie uchwyty pliku 2 (błąd standardowy) do uchwytu pliku 1 (standardowe wyjście), a następnie wyślij je do plikuoutput.log
. Innymi słowy, wyślij standardowy błąd i standardowe wyjście do pliku dziennika.2>&1 | tee output.log
jest taki sam z2>&1
bitem, łączy standardowe wyjście i standardowy błąd ze standardowym strumieniem wyjściowym. Następnie przepuszcza to przeztee
program, który wyśle standardowe wejście na standardowe wyjście (jakcat
), a także do pliku. Łączy więc dwa strumienie (błąd i dane wyjściowe), a następnie przekazuje je do terminala i pliku.Najważniejsze jest to, że pierwszy wysyła
stderr
/stdout
do pliku, podczas gdy drugi wysyła go zarówno do pliku, jak i do standardowego wyjścia (co jest prawdopodobnie to terminal, chyba że znajdujesz się w innej konstrukcji, która przekierowała standardowe wyjście).Wspominam o tej ostatniej możliwości, ponieważ możesz mieć takie rzeczy jak:
gdzie nic nie kończy się na terminalu.
źródło
cat /doesnotexist 2>&1 >output.txt
- zobaczyszcat: /doesnotexist: No such file or directory
wyświetlane na terminalu, a output.txt jest pustym plikiem.2>&1
Stosowana jest kolejność pierwszeństwa i zamykania: (dup fd2 z bieżącego fd1), a następnie>output.txt
(przekieruj fd1 do output.txt, nie zmieniając niczego innego). Innym powodem2>&1 |
jest kolejność pierwszeństwa:|
wcześniej>
.Pierwsze polecenie wykona inne zadanie:
Po
stary STDOUT zostanie zapisany (skopiowany) w STDERR, a następnie STDOUT zostanie przekierowany do pliku.
Stdout przejdzie do pliku, a stderr przejdzie do konsoli.
I w
oba strumienie zostaną przekierowane do tee. Tee zduplikuje wszelkie dane wejściowe na standardowe wyjście (konsola w twoim przypadku) i do pliku (
output.log
).I jest jeszcze jedna forma pierwszego:
spowoduje to przekierowanie zarówno STDOUT, jak i STDERR do pliku.
źródło
Te pierwsze generują tylko plik. Drugi wyświetla zarówno plik, jak i ekran.
źródło
Powodem
2>&1 | tee
jest możliwość przechwycenia zarówno stdout, jak i stderr do pliku dziennika i jednoczesnego wyświetlenia go na ekranie. Można to również zrobić>output.txt 2>&1 & tail -f
, ale nie wiadomo, kiedy zakończyła się komenda w tle - czy program został zakończony, czy działa bez wyjścia. To2>&1 | tee
był wspólny idiom dla programistów.źródło
Najpierw zobaczmy przykładowy kod:
Porównajmy wyniki:
./helloerror
+ plik: brak wiadomości; konsola: komunikat 1,2,3;
./helloerror >error.txt
+ plik: wiadomość 1,2; konsola: komunikat 3;
./helloerror 2>&1 >error.txt
+ plik: wiadomość 1,2; konsola: komunikat 3;
+ to samo co ./helloerror> error.txt
./helloerror >error.txt 2>&1
+ plik: komunikat 3,1,2; konsola: brak wiadomości;
+ zwróć uwagę, że kolejność 3 jest pierwsza, potem 1, a następnie 2
./helloerror | tee error.txt 2>&1
+ plik: wiadomość 1,2; konsola: komunikat 3,1,2;
+ zwróć uwagę, że kolejność 3 jest pierwsza, potem 1, a następnie 2
./helloerror 2>&1 | tee error.txt
+ plik: komunikat 3,1,2; konsola: komunikat 3,1,2;
Aby użyć:
./helloerror >error.txt 2>&1
-> jeśli chce się wszystkich (stdout + stderr) wiadomości w pliku, ale nie jest zapisanych na konsoli
./helloerror 2>&1 | tee error.txt
-> jeśli ktoś chce wszystkie (stdout + stderr) wiadomości w pliku i drukowane na konsoli
źródło
Oto post podsumowujący strumienie wyjściowe systemu Unix: http://www.devcodenote.com/2015/04/unix-output-streams.html
Fragment posta:
Istnieją 3 standardowe strumienie wyjściowe:
źródło