Was bedeutet "2> & 1" in der Shell?


2284

Wenn ich in einer Unix-Shell zur weiteren Bearbeitung kombinieren stderrund stdoutin den stdoutStream einbinden möchte , kann ich am Ende meines Befehls Folgendes anhängen:

2>&1

Wenn ich also headdie Ausgabe von g++verwenden möchte, kann ich Folgendes tun:

g++ lots_of_errors 2>&1 | head

so kann ich nur die ersten fehler sehen.

Ich habe immer Probleme, mich daran zu erinnern, und ich muss ständig nachschlagen, und das liegt hauptsächlich daran, dass ich die Syntax dieses bestimmten Tricks nicht vollständig verstehe.

Kann jemand dies auflösen und Charakter für Charakter erklären, was 2>&1 bedeutet?


50
@dbr Ich glaube nicht, dass es nur Bash ist - ich glaube, es ist eine Bourne-Shell-Sache; daher sh, bash, ksh, ash, dash usw.
Waffen

8
Dies ist Teil des Umleitungsabschnitts, in dem POSIX-kompatible Shells oder kurz POSIX-Shell beschrieben werden. ksh ist beispielsweise eine POSIX-Shell. Siehe: pubs.opengroup.org/onlinepubs/009695399/utilities/…
Jim Mcnamara

12
Dieses Konstrukt funktioniert auch unter Windows.
Vadzim

2
Es ist im Allgemeinen besser 2>&1als 2> / dev / null ;-)
F. Hauri

11
Ich dachte, ich würde erwähnen, dass dies |& eine Abkürzung ist, 2>&1 |wenn Sie zsh verwenden. Ich kann nicht darüber sprechen, ob dies für andere bourneähnliche Muscheln gilt oder ob es sich nur um eine zsh-Funktion handelt.
Chrixian

Antworten:


2557

Dateideskriptor 1 ist die Standardausgabe ( stdout).
Dateideskriptor 2 ist der Standardfehler (stderr ).

Hier ist ein Weg , um dieses Konstrukt zu erinnern (obwohl es nicht ganz korrekt ist): zuerst, 2>1wie ein guter Weg aussehen kann umleiten stderrzu stdout. Es wird jedoch tatsächlich als "Umleitung stderrzu einer Datei mit dem Namen 1" interpretiert . &gibt an, dass das Folgende ein Dateideskriptor und kein Dateiname ist. So wird das Konstrukt : 2>&1.


281
aber sollte es dann nicht lieber sein &2>&1?
Dokaspar

319
@Dominik: Nein, &wird nur im Zusammenhang mit Umleitungen als "Dateideskriptor" interpretiert. Das Schreiben command &2>&wird analysiert als command &und 2>&1, dh " commandim Hintergrund ausführen, dann den Befehl ausführen 2und seine Standardausgabe in seine Standardausgabe umleiten".
Adam Rosenfield

15
Warum haben sie so arkane Sachen wie diese ausgewählt? Nur neugierig.
CommaToast

81
Aber wie würden Sie stderr in eine Datei mit dem Namen '& 1' umleiten?
Martín Fixman

120
@ Martin:2>'&1'

632
echo test > afile.txt

leitet stdout an weiter afile.txt. Dies ist das gleiche wie zu tun

echo test 1> afile.txt

Um stderr umzuleiten, gehen Sie wie folgt vor:

echo test 2> afile.txt

>& ist die Syntax zum Umleiten eines Streams zu einem anderen Dateideskriptor - 0 ist stdin, 1 ist stdout und 2 ist stderr.

Sie können stdout zu stderr umleiten, indem Sie Folgendes tun:

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

Oder umgekehrt:

echo test 2>&1

Kurz gesagt ... 2>leitet stderr an eine (nicht angegebene) Datei weiter und &1leitet stderr an stdout weiter.


5
Ist das für Sie sinnvoll java ... 2&1 >> data.log? Ich habe gesehen, dass einer meiner Kollegen dies getan hat.
Thang Pham

5
@ Harry, der aussieht wie eine Shell, die nicht Bash ist, oder ein Tippfehler .. cmd 2>&1 >> somefile.logwird stdout / stderr an eine Datei anhängen - es ist im Grunde das gleiche wie oben, mit >> fileanhängen
dbr

73
@dbr cmd 2>&1 >>fileleitet stderr nicht in die Datei um, cmd >> file 2>&1tut es aber . Ordnung ist wichtig. Im ersten Fall wird stderr zum stdout der Shell umgeleitet (möglicherweise ein tty, wenn der Befehl interaktiv eingegeben wird), und dann wird stdout an die Datei weitergeleitet. Im zweiten Fall wird stdout an die Datei und dann stderr an dieselbe Stelle geleitet.
William Pursell

2
Ich mag die Antwort oben, aber es könnte ein bisschen klarer sein. "2> & 1" leitet stderr zum Ziel von stdout um. Wenn Sie also so etwas wie "ls -l >> directoryContents 2> & 1" haben, wird eine Datei mit dem Namen directoryContents den Inhalt des Arbeitsverzeichnisses anhängen. Wenn bei der Ausführung Fehler auftreten: Die Fehlermeldungen werden bei ihrem Auftreten auch an die Datei directoryContents angehängt.
Max West

1
Ist 0(or 1,2)>&0(or 1,2)wie eine Option, um die Ausgabe zu steuern? Ist das echo test >test.log 2>&1gleiche wie echo test 2>&1 >test.log?
Simin Jie

318

Einige Tricks zur Umleitung

Einige Syntax-Besonderheiten hierzu können wichtige Verhaltensweisen aufweisen. Es gibt einige kleine Proben über Umleitungen, STDERR, STDOUTund Argumente Ordnung .

1 - Überschreiben oder Anhängen?

Symbol >bedeutet Umleitung .

  • >bedeuten , an eine vollständige Datei senden und das Ziel überschreiben, falls vorhanden (siehe noclobberBash-Funktion auf # 3 später).
  • >>meine senden zusätzlich zu würde an Ziel anhängen, wenn vorhanden.

In jedem Fall würde die Datei erstellt, wenn sie nicht vorhanden wäre.

2 - Die Shell-Befehlszeile ist auftragsabhängig !!

Um dies zu testen, benötigen wir einen einfachen Befehl, der an beide Ausgänge etwas sendet :

$ 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

(Vorausgesetzt, Sie haben kein Verzeichnis mit dem Namen /tnt natürlich ;). Nun, wir haben es !!

Also mal sehen:

$ 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

Die letzte Befehlszeile wird STDERRauf der Konsole ausgegeben, und es scheint nicht das erwartete Verhalten zu sein ... Aber ...

Wenn Sie eine Nachfilterung für eine Ausgabe, die andere oder beide durchführen möchten :

$ 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 --->

Beachten Sie, dass die letzte Befehlszeile in diesem Absatz genau die gleiche ist wie im vorherigen Absatz, in dem ich geschrieben habe , dass sie nicht das erwartete Verhalten zu sein scheint (dies könnte also sogar ein erwartetes Verhalten sein).

Nun, es gibt ein paar Tricks zu Umleitungen, um an beiden Ausgängen unterschiedliche Operationen durchzuführen :

$ ( 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: &9Deskriptor würde wegen spontan auftreten ) 9>&2.

Nachtrag: nota! Mit der neuen Version von( >4.0) Es gibt eine neue Funktion und eine sexy Syntax für diese Art von Dingen:

$ 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

Und schließlich für eine solche kaskadierende Ausgabeformatierung:

$ ((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

Nachtrag: nota! Gleiche neue Syntax in beiden Richtungen:

$ 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

Wenn STDOUTSie einen bestimmten Filter durchlaufen, gehen Sie zu einem STDERRanderen und schließlich führen beide zusammengeführten Ausgänge einen dritten Befehlsfilter durch.

3 - Ein Wort zu noclobberOption und >|Syntax

Hier geht es ums Überschreiben :

Während set -o noclobberanweisen bash nicht eine vorhandene Datei zu überschreiben, die >|Syntax können Sie durch diese Einschränkung passieren:

$ 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

Die Datei wird jetzt jedes Mal überschrieben:

$ 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

Durchgehen mit >|:

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

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

Deaktivieren Sie diese Option und / oder fragen Sie nach, falls bereits festgelegt.

$ 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 - Letzter Trick und mehr ...

Um beide Ausgaben von einem bestimmten Befehl umzuleiten , sehen wir, dass eine richtige Syntax sein könnte:

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

Für diesen speziellen Fall gibt es eine Verknüpfungssyntax: &>... oder>&

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

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

Hinweis: Wenn 2>&1vorhanden, 1>&2ist auch eine korrekte Syntax:

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

4b- Nun werde ich Sie überlegen lassen:

$ 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- Wenn Sie an weiteren Informationen interessiert sind

Sie können das feine Handbuch lesen, indem Sie auf Folgendes klicken:

man -Len -Pless\ +/^REDIRECTION bash

in einem Konsole ;-)


5
Lesen Sie weiter: Wenn Ihnen das gefallen hat, können Sie es zu schätzen wissen: Wie Umleitungsmissbrauch zu seltsamen Verhaltensweisen führen kann
F. Hauri


130

Ich habe diesen brillanten Beitrag zur Weiterleitung gefunden: Alles über Weiterleitungen

Leiten Sie sowohl die Standardausgabe als auch den Standardfehler in eine Datei um

$ Befehl &> Datei

Dieser Einzeiler verwendet den &>Operator, um beide Ausgabestreams - stdout und stderr - vom Befehl in die Datei umzuleiten. Dies ist die Verknüpfung von Bash, mit der beide Streams schnell zum selben Ziel umgeleitet werden können.

So sieht die Dateideskriptortabelle aus, nachdem Bash beide Streams umgeleitet hat:

Geben Sie hier die Bildbeschreibung ein

Wie Sie sehen können, zeigen sowohl stdout als auch stderr jetzt auf file. Alles, was an stdout und stderr geschrieben wurde, wird an geschrieben file.

Es gibt verschiedene Möglichkeiten, beide Streams zum selben Ziel umzuleiten. Sie können jeden Stream nacheinander umleiten:

$ Befehl> Datei 2> & 1

Dies ist eine weitaus häufigere Methode, um beide Streams in eine Datei umzuleiten. Zuerst wird stdout in die Datei umgeleitet, und dann wird stderr so dupliziert, dass es mit stdout identisch ist. Beide Streams zeigen also auf file.

Wenn Bash mehrere Umleitungen sieht, werden diese von links nach rechts verarbeitet. Lassen Sie uns die Schritte durchgehen und sehen, wie das passiert. Bevor Sie Befehle ausführen, sieht die Dateideskriptortabelle von Bash folgendermaßen aus:

Geben Sie hier die Bildbeschreibung ein

Jetzt verarbeitet Bash die erste Umleitungsdatei. Wir haben dies schon einmal gesehen und es macht stdout auf die Datei zu verweisen:

Geben Sie hier die Bildbeschreibung ein

Als nächstes sieht Bash die zweite Umleitung 2> & 1. Wir haben diese Umleitung noch nie gesehen. Dieser dupliziert den Dateideskriptor 2, um eine Kopie des Dateideskriptors 1 zu sein, und wir erhalten:

Geben Sie hier die Bildbeschreibung ein

Beide Streams wurden in eine Datei umgeleitet.

Seien Sie hier jedoch vorsichtig! Schreiben

Befehl> Datei 2> & 1

ist nicht dasselbe wie schreiben:

$ Befehl 2> & 1> Datei

Die Reihenfolge der Weiterleitungen ist in Bash wichtig! Dieser Befehl leitet nur die Standardausgabe in die Datei um. Der stderr druckt weiterhin auf dem Terminal. Um zu verstehen, warum dies geschieht, gehen wir die Schritte noch einmal durch. Bevor Sie den Befehl ausführen, sieht die Dateideskriptortabelle folgendermaßen aus:

Geben Sie hier die Bildbeschreibung ein

Jetzt verarbeitet Bash Umleitungen von links nach rechts. Zuerst werden 2> & 1 angezeigt, sodass stderr in stdout dupliziert wird. Die Dateideskriptortabelle lautet:

Geben Sie hier die Bildbeschreibung ein

Jetzt sieht Bash die zweite Weiterleitung >fileund leitet stdout in die Datei um:

Geben Sie hier die Bildbeschreibung ein

Sehen Sie, was hier passiert? Stdout zeigt jetzt auf die Datei, aber der stderr zeigt immer noch auf das Terminal! Alles, was in stderr geschrieben wird, wird immer noch auf dem Bildschirm ausgedruckt! Seien Sie also sehr, sehr vorsichtig mit der Reihenfolge der Weiterleitungen!

Beachten Sie auch, dass in Bash schriftlich

$ Befehl &> Datei

ist genau das gleiche wie:

$ command> & file


3
Die letzten beiden sind unterschiedlich, wenn "Befehl" mit einer Zahl endet, da dies dann als optionaler Dateideskriptor für>&
MM

Sehr schöne Zeichnung und Erklärung! Könnten Sie näher erläutern, was "Duplikat" wirklich bedeutet? Sie haben erwähnt: "Dieser [2> & 1] dupliziert den Dateideskriptor 2, um eine Kopie des Dateideskriptors 1 zu sein." Es klingt so, als würde stderr zu stdout dupliziert. Aber wenn es der Fall ist, sollte ich dann auch Fehler sehen /dev/tty0?
HCSF

87

Die Zahlen beziehen sich auf die Dateideskriptoren (fd).

  • Null ist stdin
  • Eins ist stdout
  • Zwei ist stderr

2>&1 leitet fd 2 zu 1 um.

Dies funktioniert für eine beliebige Anzahl von Dateideskriptoren, wenn das Programm diese verwendet.

Sie können sehen, /usr/include/unistd.hwenn Sie sie vergessen:

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

Das heißt, ich habe C-Tools geschrieben, die nicht standardmäßige Dateideskriptoren für die benutzerdefinierte Protokollierung verwenden, sodass Sie sie nur sehen, wenn Sie sie in eine Datei oder etwas anderes umleiten.


58

Dieses Konstrukt sendet den Standardfehlerstrom ( stderr) an den aktuellen Speicherort der Standardausgabe ( stdout) - dieses Währungsproblem scheint von den anderen Antworten vernachlässigt worden zu sein.

Mit dieser Methode können Sie jedes Ausgabehandle auf ein anderes umleiten. Am häufigsten wird es jedoch verwendet, um Kanäle stdoutund stderrStreams zur Verarbeitung in einen einzelnen Stream zu kanalisieren .

Einige Beispiele sind:

# 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

Beachten Sie, dass das letzte wird nicht direkt stderrzu outfile2- es leitet es zu dem, was stdoutwar , wenn das Argument angetroffen wurde ( outfile1) und dann Umleitungen stdoutzu outfile2.

Dies erlaubt einige ziemlich raffinierte Tricks.


5
Obwohl das letzte Beispiel viel klarer wäre als: foo> outfile2 2> outfile1
Michael Cramer

3
Klarer, ja, aber das würde nicht die "positionelle" Natur der Umleitung zeigen. Das Beispiel ist erfunden, da es normalerweise nicht sinnvoll ist, dies in einer einzigen Zeile zu tun. Die Methode wird sehr nützlich, wenn verschiedene Parteien für die verschiedenen Teile der Umleitung verantwortlich sind. Zum Beispiel, wenn ein Skript ein Bit der Umleitung ausführt und Sie es mit einem anderen Bit ausführen.
Paxdiablo

5
Ich habe gerade festgestellt, dass das letzte Beispiel auch eine langjährige Verwirrung darüber auflöst, warum dies: some_program 2>&1 > /dev/nullfunktioniert nicht so : some_program > /dev/null 2>&1.
Snapfractalpop

Ihr Kommentar zum letzten Beispiel ist Gold wert :-) Ich hätte nie gedacht, dass diese Umleitungsargumente positionell sind ... Ich denke, das ist ziemlich wichtig zu wissen.
Nils-o-mat

20

2>&1ist ein POSIX-Shell-Konstrukt. Hier ist eine Aufschlüsselung, Token für Token:


2: Deskriptor der Ausgabedatei " Standardfehler ".

>&: Duplizieren Sie einen Operator für den Ausgabedateideskriptor (eine Variante des Operators für die Umleitung der Ausgabe> ). Gegeben ist [x]>&[y], dass der mit bezeichnete Dateideskriptor xeine Kopie des Ausgabedateideskriptors ist y.

1Deskription der Ausgabedatei " Standardausgabe ".

Der Ausdruck 2>&1kopiert den Dateideskriptor 1an den Speicherort 2, sodass jede Ausgabe, 2in die in der Ausführungsumgebung geschrieben wurde ("Standardfehler"), in dieselbe Datei verschoben wird, die ursprünglich von 1("Standardausgabe") beschrieben wurde.


Weitere Erklärung:

Dateideskriptor : "Eine pro Prozess eindeutige, nicht negative Ganzzahl, mit der eine geöffnete Datei zum Zweck des Dateizugriffs identifiziert wird."

Standardausgabe / -fehler : Beachten Sie den folgenden Hinweis im Abschnitt Umleitung der Shell-Dokumentation:

Geöffnete Dateien werden durch Dezimalzahlen dargestellt, die mit Null beginnen. Der größtmögliche Wert ist implementierungsdefiniert. Alle Implementierungen müssen jedoch mindestens 0 bis einschließlich 9 für die Verwendung durch die Anwendung unterstützen. Diese Nummern werden als "Dateideskriptoren" bezeichnet. Die Werte 0, 1 und 2 haben eine besondere Bedeutung und herkömmliche Verwendungen und werden durch bestimmte Umleitungsoperationen impliziert. Sie werden als Standardeingabe, Standardausgabe bzw. Standardfehler bezeichnet. Programme beziehen ihre Eingabe normalerweise von der Standardeingabe und schreiben die Ausgabe auf die Standardausgabe. Fehlermeldungen werden normalerweise bei Standardfehlern geschrieben. Den Umleitungsoperatoren können eine oder mehrere Ziffern (ohne dazwischenliegende Zeichen) vorangestellt werden, um die Dateideskriptornummer anzugeben.


19

2 ist der Konsolenstandardfehler.

1 ist die Standardausgabe der Konsole.

Dies ist das Standard-Unix, und Windows folgt auch dem POSIX.

ZB wenn du rennst

perl test.pl 2>&1

Der Standardfehler wird zur Standardausgabe umgeleitet, sodass Sie beide Ausgaben zusammen sehen können:

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

Nach der Ausführung können Sie die gesamte Ausgabe einschließlich der Fehler in der Datei debug.log anzeigen.

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

Dann geht die Standardausgabe zu out.log und der Standardfehler zu err.log.

Ich schlage vor, dass Sie versuchen, diese zu verstehen.


Das zweite Beispiel ist falsch: Da die Rangfolge der Reihenfolge STDERR zu STDOUT umgeleitet wird , wird nur Standard- STDOUT in debug.log (nicht STDERR ) geschrieben, siehe meine Antwort (Absatz 2)! Um sicherzustellen, dass beide in dieselbe Datei umgeleitet werden, müssen Sie die Umleitungsanweisungen perl test.pl > debug.log 2>&1
F. Hauri

16

So beantworten Sie Ihre Frage: Es nimmt jede Fehlerausgabe (normalerweise an stderr gesendet) und schreibt sie in die Standardausgabe (stdout).

Dies ist beispielsweise bei "more" hilfreich, wenn Sie für alle Ausgaben ein Paging benötigen. Einige Programme drucken beispielsweise Nutzungsinformationen in stderr.

Um Ihnen zu helfen, sich zu erinnern

  • 1 = Standardausgabe (wobei Programme die normale Ausgabe drucken)
  • 2 = Standardfehler (wo Programme Fehler drucken)

"2> & 1" zeigt einfach alles, was an stderr gesendet wurde, stattdessen auf stdout.

Ich empfehle auch, diesen Beitrag über Fehlerumleitungen zu lesen, in denen dieses Thema ausführlich behandelt wird.


11

Aus Sicht eines Programmierers bedeutet dies genau Folgendes:

dup2(1, 2);

Siehe die Manpage .

Zu verstehen, dass dies 2>&1eine Kopie ist, erklärt auch, warum ...

command >file 2>&1

... ist nicht dasselbe wie ...

command 2>&1 >file

Der erste sendet beide Streams an file, während der zweite Fehler an stdoutund die normale Ausgabe an sendet file.


9

Ich fand das sehr hilfreich, wenn Sie ein Anfänger sind, lesen Sie dies

Update:
Unter Linux oder Unix System senden Programme zwei Ausgaben an: Standardausgabe (stdout) und Standardfehler (stderr). Sie können diese Ausgabe in eine beliebige Datei umleiten.

Wenn Sie dies tun, wird

ls -a > output.txt

nichts in der Konsole gedruckt. Alle Ausgaben (stdout) werden in die Ausgabedatei umgeleitet.

Wenn Sie versuchen, den Inhalt einer Datei zu drucken, die nicht beendet wird, bedeutet dies, dass die Ausgabe ein Fehler ist, wie wenn Sie test.txt drucken, das im aktuellen Verzeichnis nicht vorhanden

cat test.txt > error.txt

ist

cat: test.txt :No such file or directory

Die Datei error.txt ist jedoch leer, da wir das stdout in eine Datei umleiten, die nicht stderr ist.

Daher benötigen wir einen Dateideskriptor (ein Dateideskriptor ist nichts anderes als eine positive Ganzzahl, die eine geöffnete Datei darstellt. Sie können sagen, dass der Deskriptor eine eindeutige ID der Datei ist), um der Shell mitzuteilen, welche Art von Ausgabe wir an die Datei senden. Im Unix / Linux-System 1 ist für stdout und 2 für stderr .

Wenn Sie dies jetzt tun,

ls -a 1> output.txtbedeutet dies, dass Sie die Standardausgabe (stdout) an output.txt senden.

und wenn Sie dies tun,

cat test.txt 2> error.txtbedeutet dies, dass Sie Standard Error (stderr) an error.txt senden.

&1wird verwendet, um auf den Wert des Dateideskriptors 1 (stdout) zu verweisen.

Jetzt 2>&1bedeutet der Punkt "Leiten Sie den stderr an dieselbe Stelle um, an der wir den stdout umleiten".

Jetzt können Sie dies tun

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

Sowohl die Standardausgabe (stdout) als auch der Standardfehler (stderr) werden zu output.txt umgeleitet.

Vielen Dank an Ondrej K. für den Hinweis


1
Nur-Link-Antworten sind problematisch. Der Link kann nicht mehr funktionieren und die Antwort unbrauchbar machen. Sie sollten immer genügend Details in die Antwort selbst aufnehmen.
Ondrej K.

7

Leute, erinnert euch immer an den Hinweis von paxdiablo über den aktuellen Standort des Umleitungsziels ... Es ist wichtig.

Meine persönliche Mnemonik für den 2>&1Bediener lautet:

  • Betrachten Sie &als Bedeutung 'and'oder'add'Stellen (der Charakter ist ein Amper - und nicht wahr ?)
  • So wird es: 'umleiten 2(stderr) wohin1 (stdout) bereits / aktuell ist und beide Streams hinzufügen ' .

Die gleiche Mnemonik funktioniert auch für die andere häufig verwendete Umleitung 1>&2:

  • Denk an & Bedeutung andoder add... (Sie haben eine Vorstellung vom kaufmännischen Und, ja?)
  • So wird es: 'umleiten 1(stdout) dorthin, wo 2(stderr) bereits / aktuell ist und beide Streams hinzufügen ' .

Und denken Sie immer daran: Sie müssen Umleitungsketten "vom Ende" von rechts nach links ( nicht von links nach rechts) lesen .


7

Eingabe umleiten

Die Umleitung der Eingabe bewirkt, dass die Datei, deren Name aus der Erweiterung des Wortes resultiert, zum Lesen des Dateideskriptors n oder der Standardeingabe (Dateideskriptor 0) geöffnet wird, wenn n nicht angegeben ist.

Das allgemeine Format für die Umleitung von Eingaben lautet:

[n]<word

Ausgabe umleiten

Die Umleitung der Ausgabe bewirkt, dass die Datei, deren Name aus der Erweiterung des Wortes resultiert, zum Schreiben in den Dateideskriptor n oder die Standardausgabe (Dateideskriptor 1) geöffnet wird, wenn n nicht angegeben ist. Wenn die Datei nicht vorhanden ist, wird sie erstellt. Wenn es existiert, wird es auf die Größe Null abgeschnitten.

Das allgemeine Format für die Umleitung der Ausgabe lautet:

[n]>word

Verschieben von Dateideskriptoren

Der Umleitungsoperator,

[n]<&digit-

Verschiebt die Dateideskriptor-Ziffer in den Dateideskriptor n oder in die Standardeingabe (Dateideskriptor 0), wenn n nicht angegeben ist. Die Ziffer wird geschlossen, nachdem sie auf n dupliziert wurde.

Ebenso der Umleitungsoperator

[n]>&digit-

Verschiebt die Dateideskriptordiffer in den Dateideskriptor n oder die Standardausgabe (Dateideskriptor 1), wenn n nicht angegeben ist.

Ref:

man bash

Geben Sie ein /^REDIRECT, um zu dem redirectionAbschnitt zu gelangen, und erfahren Sie mehr ...

Eine Online-Version finden Sie hier: 3.6 Weiterleitungen

PS:

Die meiste Zeit manwar das mächtige Werkzeug, um Linux zu lernen.


6

Vorausgesetzt, dass /foodies auf Ihrem System nicht vorhanden ist und /tmp

$ ls -l /tmp /foo

druckt den Inhalt von /tmpund druckt eine Fehlermeldung für/foo

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

sendet den Inhalt von /tmpan /dev/nullund druckt eine Fehlermeldung für/foo

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

wird genau das gleiche tun (beachten Sie die 1 )

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

druckt den Inhalt von /tmpund sendet die Fehlermeldung an/dev/null

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

sendet sowohl die Auflistung als auch die Fehlermeldung an /dev/null

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

ist eine Abkürzung


5

Dies ist wie das Übergeben des Fehlers an das Standardout oder das Terminal.

Das heißt, cmdist kein Befehl:

$cmd 2>filename
cat filename

command not found

Der Fehler wird wie folgt an die Datei gesendet:

2>&1

Standardfehler wird an das Terminal gesendet.


1

0 für Eingabe, 1 für stdout und 2 für stderr.

Ein Tipp : somecmd >1.txt 2>&1ist richtig, während somecmd 2>&1 >1.txtvöllig falsch ohne Wirkung!


1

unix_commands 2>&1

Dies wird verwendet, um Fehler auf das Terminal zu drucken.

Das Folgende veranschaulicht den Prozess

  • Wenn Fehler erzeugt werden, werden sie in den Standardfehlerspeicheradresse &2"Puffer" geschrieben, auf den der Standardfehlerstrom 2verweist.
  • Wenn eine Ausgabe erzeugt wird, wird sie in den Standardausgabespeicheradresse &1"Puffer" geschrieben, auf den der Standardausgabestream 1verweist.

Nehmen Sie also den unix_commandsStandardfehlerstrom 2und leiten Sie >den Strom (der Fehler) an die Standardausgabespeicheradresse um &1, damit sie zum Terminal gestreamt und gedruckt werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.