Co w skorupce oznacza „2> i 1”?

2282

W powłoce Unix, jeśli chce się połączyć stderri stdoutdo stdoutstrumienia do dalszej manipulacji, mogę dołączyć następujące na koniec mojego polecenia:

2>&1

Więc jeśli chcę użyć headna wyjściu z g++, mogę zrobić coś takiego:

g++ lots_of_errors 2>&1 | head

więc widzę tylko kilka pierwszych błędów.

Zawsze mam problem z zapamiętywaniem tego i ciągle muszę to sprawdzać, a to głównie dlatego, że nie do końca rozumiem składnię tej konkretnej sztuczki.

Czy ktoś może to przełamać i wyjaśnić znak po znaku, co 2>&1 to znaczy?

Tristan Havelick
źródło
50
@dbr Nie sądzę, że to tylko bash - wierzę, że jest to rzecz z bourne shell; stąd sh, bash, ksh, ash, dash itp.
pistolety
8
Jest to część akapitu przekierowania opisującego powłoki zgodne z POSIX lub w skrócie powłokę POSIX. ksh jest na przykład powłoką POSIX. Zobacz: pubs.opengroup.org/onlinepubs/009695399/utilities/…
Jim Mcnamara
12
Ta konstrukcja działa również w systemie Windows.
Vadzim
2
Ogólnie lepiej jest robić 2>&1niż 2> / dev / null ;-)
F. Hauri
11
Myślałem, że wspomnę, że |& jest to skrót, 2>&1 |jeśli używasz zsh. Nie mogę porozmawiać o tym, czy dotyczy to innych pocisków typu bourne, czy też jest to funkcja tylko zsh.
chrixian,

Odpowiedzi:

2554

Deskryptor pliku 1 jest standardowym wyjściem ( stdout).
Deskryptor pliku 2 jest standardowym błędem ( stderr).

Oto jeden sposób, aby zapamiętać ten konstrukt (choć nie jest to do końca prawda): w pierwszym, 2>1może wyglądać dobry sposób przekierować stderrdo stdout. Jednak będzie to interpretowane jako „przekierowanie stderrdo pliku o nazwie 1”. &wskazuje, że poniżej znajduje się deskryptor pliku, a nie nazwa pliku. Więc konstrukt postać: 2>&1.

Ayman Hourieh
źródło
280
ale czy nie powinno tak być &2>&1?
dokaspar
319
@Dominik: Nie, &interpretowany jest jedynie jako „deskryptor pliku” w kontekście przekierowań. Pisanie command &2>&jest analizowane jako command &i 2>&1, tzn. „ commandUruchom w tle, a następnie uruchom polecenie 2i przekieruj jego stdout na stdout”.
Adam Rosenfield
15
Dlaczego wybrali takie tajemnicze rzeczy jak to? Po prostu ciekawy.
CommaToast
81
Ale jak przekierowałbyś stderr do pliku o nazwie „& 1”?
Martín Fixman
120
@Martin:2>'&1'
632
echo test > afile.txt

przekierowuje standardowe wyjście na afile.txt. To jest to samo co robienie

echo test 1> afile.txt

Aby przekierować stderr, wykonujesz:

echo test 2> afile.txt

>& to składnia przekierowująca strumień do innego deskryptora pliku - 0 oznacza standardowe wejście, 1 standardowe wyjście, a 2 standardowe.

Możesz przekierować stdout na stderr, wykonując:

echo test 1>&2 # or echo test >&2

Lub odwrotnie:

echo test 2>&1

Krótko mówiąc ... 2>przekierowuje stderr do (nieokreślonego) pliku, dołączając &1przekierowuje stderr do standardowego wyjścia.

dbr
źródło
5
czy to ma dla ciebie jakiś sens java ... 2&1 >> data.log, widziałem, jak zrobił to jeden z moich kolegów?
Thang Pham
5
@Harry, który wygląda jak powłoka, która nie jest bashem, lub literówka .. cmd 2>&1 >> somefile.logdołączy plik stdout / stderr do pliku - jest w zasadzie taki sam jak powyżej, z >> filedołączeniem
dbr
73
@dbr cmd 2>&1 >>filenie przekierowuje stderr do pliku, ale cmd >> file 2>&1tak. Zamówienie ma znaczenie. W pierwszym przypadku stderr jest przekierowywany na standardowe wyjście powłoki (być może tty, jeśli polecenie zostanie wprowadzone interaktywnie), a następnie standardowe wyjście jest kierowane do pliku. W drugim przypadku stdout jest kierowany do pliku, a następnie stderr jest kierowany w to samo miejsce.
William Pursell
2
Podoba mi się powyższa odpowiedź, ale może być odrobinę wyraźniejsza. „2> i 1” przekierowuje stderr do celu standardowego. Więc jeśli masz coś takiego jak „ls -l >> directoryContents 2> & 1” Wynikiem będzie plik o nazwie directoryContents, do którego zostanie dołączona zawartość katalogu roboczego. Jeśli wystąpią jakiekolwiek błędy w wykonaniu: komunikaty o błędach będą również dołączane do pliku directoryContents, w miarę ich pojawiania się.
Max West
1
Czy jest 0(or 1,2)>&0(or 1,2)jak opcja kontroli wyjścia? Czy to echo test >test.log 2>&1samo co echo test 2>&1 >test.log?
Simin Jie
318

Kilka sztuczek na temat przekierowania

Niektóre szczegóły składni na ten temat mogą mieć ważne zachowania. Istnieje kilka małych próbek o przekierowania, STDERR, STDOUT, i argumenty zamawiającego .

1 - Nadpisywanie czy dołączanie?

Symbol >oznacza przekierowanie .

  • >oznacza wysyłanie do jako kompletnego ukończonego pliku , nadpisywanie celu, jeśli istnieje (patrz noclobberfunkcja bash w # 3 później).
  • >>oznacza, że wysyłanie oprócz dołączałoby do celu, jeśli istnieje.

W każdym razie plik zostałby utworzony, gdyby nie istniał.

2 - Wiersz poleceń powłoki zależy od kolejności !!

Do przetestowania tego potrzebujemy prostego polecenia, które wyśle ​​coś na oba wyjścia :

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(Oczywiście, że nie masz katalogu o nazwie /tnt;). Cóż, mamy to !!

Zobaczmy więc:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

Ostatni wiersz poleceń zrzuca STDERRkonsolę i wydaje się, że nie jest to oczekiwane zachowanie ... Ale ...

Jeśli chcesz wykonać filtrowanie wpisów dotyczące jednego wyjścia, drugiego lub obu:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

Zauważ, że ostatni wiersz polecenia w tym akapicie jest dokładnie taki sam jak w poprzednim akapicie, w którym napisałem, wydaje się, że nie jest to oczekiwane zachowanie (więc może to być nawet oczekiwane zachowanie).

Cóż, jest kilka sztuczek na temat przekierowań, aby wykonać inną operację na obu wyjściach :

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

Nota: &9deskryptor wystąpiłby spontanicznie z powodu ) 9>&2.

Dodatek: nota! Dzięki nowej wersji( >4.0) dostępna jest nowa funkcja i bardziej seksowna składnia do robienia takich rzeczy:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

I wreszcie dla takiego kaskadowego formatowania wyjściowego:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Dodatek: nota! Ta sama nowa składnia na dwa sposoby:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Gdzie STDOUTprzechodzą przez określony filtr, STDERRdo drugiego i na końcu oba połączone wyjścia przechodzą przez trzeci filtr poleceń.

3 - Słowo o noclobberopcji i >|składni

Chodzi o nadpisywanie :

Choć set -o noclobberInstruct bash aby nie nadpisać istniejącego pliku, >|składnia pozwala przechodzić przez to ograniczenie:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

Plik jest zastępowany za każdym razem, a teraz:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

Przekaż za pomocą >|:

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

Wyłączenie tej opcji i / lub sprawdzenie, czy jest już ustawione.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 - Ostatnia sztuczka i więcej ...

Przekierowując oba dane wyjściowe z danego polecenia, widzimy, że poprawna składnia może być:

$ ls -ld /tmp /tnt >/dev/null 2>&1

w tym szczególnym przypadku istnieje składnia skrótu: &>... lub>&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

Uwaga: jeśli 2>&1istnieje, 1>&2to również poprawna składnia:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b- Teraz pozwolę ci pomyśleć o:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c- Jeśli chcesz uzyskać więcej informacji

Możesz przeczytać dokładną instrukcję, naciskając:

man -Len -Pless\ +/^REDIRECTION bash

w konsola ;-)

F. Hauri
źródło
5
Dalsza lektura: Jeśli Ci się podobało, możesz docenić: Jak nadużycie przekierowania może dać dziwne zachowania
F. Hauri
130

Znalazłem ten świetny post na temat przekierowań: Wszystko o przekierowaniach

Przekieruj zarówno standardowe wyjście, jak i standardowy błąd do pliku

$ polecenie i> plik

Ten jednowierszowy używa &>operatora do przekierowywania obu strumieni wyjściowych - stdout i stderr - z polecenia do pliku. Jest to skrót Basha do szybkiego przekierowywania obu strumieni do tego samego miejsca docelowego.

Oto jak wygląda tabela deskryptorów plików po przekierowaniu obu strumieni przez Bash:

Wpisz opis zdjęcia tutaj

Jak widać, zarówno stdout, jak i stderr wskazują teraz file. Więc wszystko, co napisano na stdout i stderr, zostaje napisane na file.

Istnieje kilka sposobów przekierowania obu strumieni do tego samego miejsca docelowego. Możesz przekierowywać każdy strumień jeden po drugim:

$ polecenie> plik 2> i 1

Jest to o wiele bardziej powszechny sposób przekierowywania obu strumieni do pliku. Najpierw stdout jest przekierowywany do pliku, a następnie stderr jest duplikowany, aby był taki sam jak stdout. Tak więc oba strumienie kończą się na file.

Gdy Bash widzi kilka przekierowań, przetwarza je od lewej do prawej. Przejdźmy przez kolejne kroki i zobaczmy, jak to się dzieje. Przed uruchomieniem jakichkolwiek poleceń tabela deskryptorów plików Bash wygląda następująco:

Wpisz opis zdjęcia tutaj

Teraz Bash przetwarza pierwszy plik przekierowania>. Widzieliśmy to już wcześniej i sprawia, że ​​stdout wskazuje na plik:

Wpisz opis zdjęcia tutaj

Następnie Bash widzi drugie przekierowanie 2> i 1. Nigdy wcześniej nie widzieliśmy tego przekierowania. Ten powiela deskryptor pliku 2 jako kopię deskryptora pliku 1 i otrzymujemy:

Wpisz opis zdjęcia tutaj

Oba strumienie zostały przekierowane do pliku.

Uważaj jednak tutaj! Pisanie

polecenie> plik 2> i 1

to nie to samo co pisanie:

$ polecenie 2> i 1> plik

Kolejność przekierowań ma znaczenie w Bash! To polecenie przekierowuje tylko standardowe wyjście do pliku. Stderr nadal będzie drukował na terminalu. Aby zrozumieć, dlaczego tak się dzieje, przejdźmy ponownie przez kolejne kroki. Tak więc przed uruchomieniem polecenia tabela deskryptorów plików wygląda następująco:

Wpisz opis zdjęcia tutaj

Teraz Bash przetwarza przekierowania od lewej do prawej. Najpierw widzi 2> i 1, więc powiela stderr do stdout. Tabela deskryptorów plików staje się:

Wpisz opis zdjęcia tutaj

Teraz Bash widzi drugie przekierowanie >filei przekierowuje standardowe wyjście do pliku:

Wpisz opis zdjęcia tutaj

Widzisz co się tutaj dzieje? Stdout wskazuje teraz na plik, ale stderr nadal wskazuje na terminal! Wszystko, co zostanie napisane do stderr, nadal zostanie wydrukowane na ekranie! Bądź więc bardzo, bardzo ostrożny z kolejnością przekierowań!

Zauważ też, że w Bash pisze

$ polecenie i> plik

jest dokładnie taki sam jak:

$ polecenie> i plik

Deen John
źródło
3
Dwa ostatnie są różne, jeśli „polecenie” kończy się liczbą, ponieważ jest to traktowane jako opcjonalny deskryptor pliku dla>&
MM
Bardzo fajny rysunek i wyjaśnienie! Czy mógłbyś wyjaśnić, co tak naprawdę oznacza „duplikat”? Wspomniałeś: „Ten [2> i 1] powiela deskryptor pliku 2 jako kopię deskryptora pliku 1”. Wygląda na to, że stderr zostaje zduplikowany na standardowe wyjście. Ale jeśli tak jest, czy powinienem również zobaczyć błąd /dev/tty0?
HCSF
87

Liczby odnoszą się do deskryptorów plików (fd).

  • Zero jest stdin
  • Jeden jest stdout
  • Dwa to stderr

2>&1 przekierowuje fd 2 na 1.

Działa to dla dowolnej liczby deskryptorów plików, jeśli program ich używa.

Możesz sprawdzić, /usr/include/unistd.hjeśli je zapomnisz:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

Powiedziałem, że napisałem narzędzia C, które używają niestandardowych deskryptorów plików do niestandardowego rejestrowania, więc nie widzisz go, dopóki nie przekierujesz go do pliku lub czegoś innego.

Colin Burnett
źródło
58

Ta konstrukcja wysyła standardowy strumień błędów ( stderr) do bieżącej lokalizacji standardowego wyjścia ( stdout) - ten problem walutowy wydaje się być zaniedbany przez inne odpowiedzi.

Za pomocą tej metody można przekierować dowolny uchwyt wyjściowy na inny, ale najczęściej jest on używany do kierowania stdouti stderrprzesyłania strumieni do jednego strumienia w celu przetworzenia.

Oto niektóre przykłady:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

Zauważ, że ten ostatni będzie nie kierować stderrdo outfile2- przekierowuje je do tego, co stdoutbyło, gdy argument napotkano ( outfile1), a następnie przekierowuje stdoutdo outfile2.

Pozwala to na dość wyrafinowane oszustwo.

paxdiablo
źródło
5
Chociaż ten ostatni przykład byłby o wiele jaśniejszy: foo> outfile2 2> outfile1
Michael Cramer
3
Jasniejsze, tak, ale to nie pokazuje „pozycyjnej” natury przekierowania. Przykład jest wymyślony, ponieważ zazwyczaj nie jest to przydatne w jednym wierszu - metoda staje się naprawdę przydatna, gdy różne strony są odpowiedzialne za różne części przekierowania. Na przykład, gdy skrypt dokonuje jednego przekierowania, a ty uruchamiasz go z innym bitem.
paxdiablo
5
Właśnie uświadomiłem sobie, że ostatni przykład rozwiązuje również długofalowego zamieszanie miałem odnośnie tego, dlaczego: some_program 2>&1 > /dev/nullnie działa tak: some_program > /dev/null 2>&1.
snapfractalpop
Twój komentarz do ostatniego przykładu jest wart swoich liter w złocie :-) Nigdy nie myślałem, że te przekierowujące argumenty są pozycyjne ... Myślę, że to bardzo ważne, aby wiedzieć.
Nils-o-mat
20

2>&1jest konstrukcją powłoki POSIX. Oto podział, token po tokenie:


2: Deskryptor pliku wyjściowego „ Błąd standardowy ”.

>&: Zduplikuj operator deskryptora pliku wyjściowego (wariant operatora przekierowania danych wyjściowych> ). Biorąc pod uwagę [x]>&[y], deskryptor pliku oznaczony jako xjest tworzony jako kopia deskryptora pliku wyjściowego y.

1Deskryptor pliku wyjściowego „ Standardowe wyjście ”.

Wyrażenie 2>&1kopiuje deskryptor pliku 1do lokalizacji 2, więc każde wyjście zapisane w 2(„błąd standardowy”) w środowisku wykonawczym trafia do tego samego pliku, który został pierwotnie opisany przez 1(„wyjście standardowe”).


Dalsze wyjaśnienia:

Deskryptor pliku : „Unikalna na liczbę procesów, nieujemna liczba całkowita używana do identyfikowania otwartego pliku w celu uzyskania dostępu do pliku”.

Standardowe wyjście / błąd : Zapoznaj się z następującą uwagą w sekcji Przekierowanie dokumentacji powłoki:

Otwarte pliki są reprezentowane przez liczby dziesiętne zaczynające się od zera. Największą możliwą wartością jest implementacja; jednak wszystkie implementacje obsługują co najmniej od 0 do 9 włącznie, do wykorzystania przez aplikację. Liczby te nazywane są „deskryptorami plików”. Wartości 0, 1 i 2 mają specjalne znaczenie i konwencjonalne zastosowania i są implikowane przez pewne operacje przekierowania; są one określane odpowiednio jako standardowe wejście, standardowe wyjście i standardowy błąd. Programy zwykle pobierają dane wejściowe ze standardowego wejścia i zapisują dane wyjściowe na standardowym wyjściu. Komunikaty o błędach są zwykle zapisywane przy standardowych błędach. Operatory przekierowania mogą być poprzedzone jedną lub większą liczbą cyfr (bez dozwolonych znaków pośrednich) w celu oznaczenia numeru deskryptora pliku.

Wjordan
źródło
19

2 jest standardowym błędem konsoli.

1 to standardowe wyjście konsoli.

Jest to standardowy Uniks, a system Windows również postępuje zgodnie z POSIX.

Np. Kiedy biegniesz

perl test.pl 2>&1

błąd standardowy jest przekierowywany na standardowe wyjście, dzięki czemu można zobaczyć oba wyjścia razem:

perl test.pl > debug.log 2>&1

Po wykonaniu możesz wyświetlić wszystkie dane wyjściowe, w tym błędy, w pliku debug.log.

perl test.pl 1>out.log 2>err.log

Następnie standardowe wyjście przechodzi do out.log, a standardowy błąd do err.log.

Sugeruję, abyś spróbował je zrozumieć.

Marcus Thornton
źródło
Druga próbka jest niepoprawna: ponieważ pierwszeństwo kolejności STDERR jest przekierowywane do STDOUT , tylko domyślny STDOUT zostanie zapisany do debug.log (nie STDERR ) zobacz moją odpowiedź (akapit # 2)! Aby upewnić się, że oba zostaną przekierowane do tego samego pliku, musisz odwrócić dyrektywy przekierowań:perl test.pl > debug.log 2>&1
F. Hauri
16

Aby odpowiedzieć na twoje pytanie: Pobiera każdy wynik błędu (zwykle wysyłany do stderr) i zapisuje go na standardowe wyjście (stdout).

Jest to pomocne, na przykład „więcej”, gdy potrzebujesz stronicowania dla wszystkich danych wyjściowych. Niektóre programy, takie jak drukowanie informacji o użyciu do stderr.

Aby pomóc ci zapamiętać

  • 1 = standardowe wyjście (gdzie programy drukują normalne wyjście)
  • 2 = błąd standardowy (w przypadku błędów drukowania programów)

„2> i 1” po prostu wskazuje wszystko wysłane do stderr, zamiast do stdout.

Polecam również przeczytanie tego postu na temat przekierowywania błędów, gdy ten temat jest szczegółowo opisany.

Andrioid
źródło
11

Z punktu widzenia programisty oznacza to dokładnie to:

dup2(1, 2);

Zobacz stronę manuala .

Zrozumienie, że 2>&1jest to kopia, wyjaśnia również, dlaczego ...

command >file 2>&1

... to nie to samo co ...

command 2>&1 >file

Pierwszy wyśle ​​oba strumienie do file, a drugi wyśle ​​błędy stdouti zwykłe wyjście do file.

ams
źródło
9

Uważam to za bardzo pomocne, jeśli jesteś początkującym, przeczytaj to

Aktualizacja:
W systemie Linux lub Unix istnieją dwa miejsca, w których programy wysyłają dane wyjściowe: Standardowe wyjście (stdout) i Standardowy błąd (stderr) . Możesz przekierować te dane wyjściowe do dowolnego pliku.

Tak, jak to zrobisz

ls -a > output.txt

Nic nie zostanie wydrukowane w konsoli, wszystkie dane wyjściowe (standardowe wyjście) zostaną przekierowane do pliku wyjściowego.

A jeśli spróbujesz wydrukować zawartość dowolnego pliku, który nie wychodzi, oznacza to, że na wyjściu pojawi się błąd, tak jak podczas drukowania test.txt, którego nie ma w bieżącym katalogu

cat test.txt > error.txt

Wyjście będzie

cat: test.txt :No such file or directory

Ale plik error.txt będzie pusty, ponieważ przekierowujemy stdout do pliku innego niż stderr.

więc potrzebujemy deskryptora pliku (deskryptor pliku to nic innego jak dodatnia liczba całkowita reprezentująca otwarty plik. Można powiedzieć, że deskryptor jest unikalnym identyfikatorem pliku), aby powiedzieć powłoce, jaki typ danych wyjściowych wysyłamy do pliku. W systemie Unix / Linux 1 jest dla standardowego wyjścia, a 2 dla standardowego .

więc teraz, jeśli to zrobisz,

ls -a 1> output.txtoznacza to, że wysyłasz Standardowe wyjście (stdout) do output.txt.

a jeśli to zrobisz,

cat test.txt 2> error.txtoznacza to, że wysyłasz błąd standardowy (stderr) na error.txt.

&1służy do odwoływania się do wartości deskryptora pliku 1 (standardowe wyjście).

Teraz do rzeczy 2>&1oznacza „Przekieruj stderr w to samo miejsce, w którym przekierowujemy stdout”

Teraz możesz to zrobić

cat maybefile.txt > output.txt 2>&1

zarówno Standardowe wyjście (stdout), jak i Standardowy błąd (stderr) zostaną przekierowane do output.txt.

Dzięki Ondrej K. za wskazanie

Küñdàñ Börà
źródło
1
Link tylko odpowiedzi są problematyczne. Link może stać się niedziałający, co czyni odpowiedź bezużyteczną. Zawsze powinieneś zawrzeć wystarczającą ilość szczegółów w samej odpowiedzi.
Ondrej K.
7

Ludzie, zawsze pamiętam wskazówkę paxdiablo na temat aktualnej lokalizacji docelowej przekierowania ... To jest ważne.

Mój osobisty mnemonik dla 2>&1operatora jest następujący:

  • Pomyśl o &znaczeniu 'and'lub 'add'(postać to ampery - i prawda?)
  • Staje się więc: „przekieruj 2(stderr) do miejsca 1(stdout) już / obecnie jest i dodaj oba strumienie” .

Ta sama mnemoniczna działa również w przypadku innych często używanych przekierowań 1>&2:

  • Pomyśl o &znaczeniu andlub add... (masz pomysł na ampersand, tak?)
  • Staje się więc: „przekieruj 1(stdout) tam, gdzie 2(stderr) już / obecnie jest i dodaj oba strumienie” .

I zawsze pamiętaj: musisz czytać łańcuchy przekierowań „od końca”, od prawej do lewej ( nie od lewej do prawej).

Kurt Pfeifle
źródło
7

Przekierowywanie danych wejściowych

Przekierowanie danych wejściowych powoduje otwarcie pliku, którego nazwa wynika z rozwinięcia słowa, do odczytu w deskryptorze pliku n lub standardowego wejścia (deskryptor pliku 0), jeśli nie określono n.

Ogólny format przekierowywania danych wejściowych to:

[n]<word

Przekierowanie danych wyjściowych

Przekierowanie wyjścia powoduje, że plik, którego nazwa wynika z rozwinięcia słowa, jest otwierany do zapisu w deskryptorze pliku n lub standardowym wyjściu (deskryptor pliku 1), jeśli n nie jest określony. Jeśli plik nie istnieje, jest tworzony; jeśli istnieje, jest obcinany do zera.

Ogólny format przekierowywania danych wyjściowych to:

[n]>word

Przenoszenie deskryptorów plików

Operator przekierowania,

[n]<&digit-

przenosi cyfrę deskryptora pliku do deskryptora pliku n lub standardowego wejścia (deskryptor pliku 0), jeśli n nie jest określone. cyfra jest zamykana po skopiowaniu do n.

Podobnie operator przekierowania

[n]>&digit-

przenosi cyfrę deskryptora pliku do deskryptora pliku n lub na standardowe wyjście (deskryptor pliku 1), jeśli n nie jest określone.

Ref:

man bash

Wpisz, /^REDIRECTaby zlokalizować redirectionsekcję i dowiedz się więcej ...

Dostępna jest wersja online: 3.6 Przekierowania

PS:

Wiele czasu manbyło potężnym narzędziem do nauki Linuksa.

Yurenchen
źródło
6

Pod warunkiem, że /foonie istnieje w systemie i /tmp

$ ls -l /tmp /foo

wydrukuje zawartość /tmpi wydrukuje komunikat błędu dla/foo

$ ls -l /tmp /foo > /dev/null

wyśle zawartość od /tmpcelu /dev/nulli wydrukować komunikat o błędzie dla/foo

$ ls -l /tmp /foo 1> /dev/null

zrobi dokładnie to samo (zwróć uwagę na 1 )

$ ls -l /tmp /foo 2> /dev/null

wydrukuje zawartość /tmpi wyśle ​​komunikat o błędzie na adres/dev/null

$ ls -l /tmp /foo 1> /dev/null 2> /dev/null

wyśle ​​zarówno wpis, jak i komunikat błędu do /dev/null

$ ls -l /tmp /foo > /dev/null 2> &1

jest skrótem

Matijs
źródło
5

To jest jak przekazanie błędu do standardowego wyjścia lub terminala.

Oznacza to, że cmdnie jest poleceniem:

$cmd 2>filename
cat filename

command not found

Błąd jest wysyłany do pliku w następujący sposób:

2>&1

Standardowy błąd jest wysyłany do terminala.

Kalanidhi
źródło
1

0 dla wejścia, 1 dla standardu i 2 dla standardu.

Jedna wskazówka : somecmd >1.txt 2>&1jest poprawna, podczas gdy somecmd 2>&1 >1.txtcałkowicie błędna bez efektu!

ch271828n
źródło
1

unix_commands 2>&1

Służy do drukowania błędów na terminalu.

Poniżej przedstawiono proces

  • Błędy powstające są zapisywane do standardowego adresu pamięci błędów &2„bufor”, z którego pochodzi standardowy strumień błędów2 odwołuje się .
  • Po wygenerowaniu dane wyjściowe są zapisywane w standardowym adresie pamięci &1„bufor”, z którego 1odwołuje się standardowy strumień wyjściowy .

Tak więc weź unix_commandsstandardowy strumień błędów 2i przekieruj >strumień (błędów) na standardowy adres pamięci wyjściowej &1, aby były one przesyłane strumieniowo do terminala i drukowane.

tfmontague
źródło