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


In einer Unix-Shell, wenn ich kombinieren möchte stderr und stdout in die stdout Stream für weitere Manipulation, kann ich am Ende meines Befehls Folgendes anhängen:

2>&1

Also, wenn ich es benutzen möchte head auf der Ausgabe von g++Ich kann so etwas machen:

g++ lots_of_errors 2>&1 | head

also kann ich nur die ersten paar Fehler sehen.

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

Kann jemand das aufteilen und Charakter für Charakter erklären? 2>&1  meint?


1734
2018-05-03 22:57


Ursprung


Antworten:


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

Hier ist eine Möglichkeit, sich an dieses Konstrukt zu erinnern (obwohl es nicht ganz genau ist): 2>1 kann wie eine gute Möglichkeit zur Umleitung aussehen stderr zu stdout. Es wird jedoch tatsächlich als "Weiterleitung" interpretiert stderr in eine Datei mit dem Namen 1". & Gibt an, dass ein Dateideskriptor und kein Dateiname folgt. So wird das Konstrukt: 2>&1.


1942
2018-05-03 23:04



echo test > afile.txt

leitet stdout nach afile.txt. Das ist dasselbe wie das Tun

echo test 1> afile.txt

Um stderr umzuleiten, tun Sie:

echo test 2> afile.txt

>& ist die Syntax, um einen Stream zu einem anderen Dateideskriptor umzuleiten - 0 ist stdin, 1 ist stdout und 2 ist stderr.

Sie können stdout auf 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 spezifizierte) Datei um und fügt sie hinzu &1 leitet stderr nach stdout um.


481
2018-05-03 22:59



Einige Tricks zur Umleitung

Einige Besonderheiten der Syntax können wichtige Verhaltensweisen haben. Es gibt einige kleine Beispiele zu Weiterleitungen, STDERR, STDOUTund Argumente Bestellung.

1 - Überschreiben oder anhängen?

Symbol > bedeuten Umleitung.

  • > bedeuten senden Sie als Ganzes abgeschlossene DateiÜberschreiben des Ziels, falls vorhanden (siehe noclobber Bash-Funktion bei #3 später).
  • >> bedeuten zusätzlich senden an würde an Ziel anhängen, wenn vorhanden.

In jedem Fall würde die Datei erstellt werden, wenn sie nicht existiert.

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

Um das zu testen, brauchen wir ein einfacher Befehl, der etwas an beiden Ausgängen 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 namens /tnt, Na sicher ;). 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 gelöscht STDERR zur Konsole, und es scheint nicht das erwartete Verhalten zu sein ... Aber ...

Wenn Sie etwas machen wollen Nachfilterung über einen Ausgang, den anderen oder beide:

$ 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 wie im vorherigen Absatz ist, wo ich geschrieben habe scheinen nicht das erwartete Verhalten zu sein (Dies könnte sogar ein erwartetes Verhalten sein).

Nun, es gibt ein paar Tricks über Umleitungen, z verschiedene Operationen an beiden Ausgängen durchfü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

Kein: &9Deskriptor würde spontan wegen auftreten ) 9>&2.

Nachtrag: NOTA! Mit der neuen Version von  (>4.0) Es gibt ein neues Feature und eine sexyere 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

Woher STDOUT gehe durch einen bestimmten Filter, STDERR zu einem anderen und schließlich beide Ausgänge zusammengeführt durch einen dritten Befehlsfilter.

3 - Ein Wort über noclobber Option und >| Syntax

Das ist ungefähr Überschreiben:

Während set -o noclobber anweisen bash zu nicht überschreiben Sie eine vorhandene Datei, die >| Syntax lässt Sie 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 jedes Mal überschrieben, also jetzt:

$ 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

Pass mit durch >|:

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

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

Diese Option wird deaktiviert und / oder gefragt, ob sie bereits festgelegt wurde.

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

Zum Umleiten beide Ausgabe von einem gegebenen Befehl, sehen wir, dass eine richtige Syntax sein könnte:

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

dafür Besondere Fall, es gibt eine Abkürzungssyntax: &> ... oder >&

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

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

Nota: wenn 2>&1 existieren, 1>&2 ist auch eine korrekte Syntax:

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

4b- Nun, ich werde dich darüber nachdenken 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 interessiert sind Mehr Information

Sie können das gute Handbuch lesen, indem Sie drücken:

man -Len -Pless\ +/^REDIRECTION bash

in einem  Konsole ;-)


256
2018-04-29 16:33



Die Nummern beziehen sich auf die Dateideskriptoren (fd).

  • Null ist stdin 
  • Einer 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 sie verwendet.

Sie können schauen /usr/include/unistd.h wenn du sie vergisst:

/* 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-Standard-Dateideskriptoren für die benutzerdefinierte Protokollierung verwenden, so dass Sie es nicht sehen, es sei denn, Sie leiten es in eine Datei oder etwas um.


67
2018-05-03 22:58



Dieses Konstrukt sendet den Standardfehlerstrom (stderr) zum Strom Standort der Standardausgabe (stdout) - Dieses Währungsproblem scheint von den anderen Antworten vernachlässigt worden zu sein.

Mit dieser Methode können Sie alle Ausgabe-Handle auf eine andere umleiten, aber sie wird am häufigsten zum Channeln verwendet stdout und stderr Streams in einem einzigen Stream für die Verarbeitung.

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 Direkte stderr zu outfile2 - Es leitet es zu was um stdout war, als das Argument gefunden wurde (outfile1) und dann Weiterleitungen stdout zu outfile2.

Dies ermöglicht einige ziemlich raffinierte Tricks.


49
2018-05-03 23:54



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

Leiten Sie die Standardausgabe und den Standardfehler in eine Datei um

$ Befehl &> Datei

Dieser One-Liner verwendet die &> Operator, um beide Ausgabeströme - stdout und stderr - von Befehl zu Datei umzuleiten. Dies ist Bashs Verknüpfung, um beide Streams schnell zum selben Ziel zu leiten.

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

Enter image description here

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

Es gibt mehrere Möglichkeiten, beide Streams an dasselbe Ziel umzuleiten. Sie können jeden Stream nacheinander umleiten:

$ Befehl> Datei 2> & 1

Dies ist eine häufigere Möglichkeit, beide Streams in eine Datei umzuleiten. Das erste stdout wird in die Datei umgeleitet, und dann wird stderr dupliziert, um dasselbe wie stdout zu sein. Also zeigen beide Ströme auf file.

Wenn Bash mehrere Umleitungen sieht, werden sie von links nach rechts verarbeitet. Lass uns durch die Schritte gehen und sehen, wie das passiert. Bevor Sie irgendwelche Befehle ausführen, sieht Bashs Dateibeschreibung folgendermaßen aus:

Enter image description here

Jetzt verarbeitet Bash die erste Umleitungsdatei. Wir haben das schon einmal gesehen und es macht einen Standout-Punkt auf Datei:

Enter image description here

Next Bash sieht die zweite Umleitung 2> & 1. Wir haben diese Umleitung bisher nicht gesehen. Dieser dupliziert den Dateideskriptor 2 als Kopie des Dateideskriptors 1 und wir erhalten:

Enter image description here

Beide Streams wurden in die Datei umgeleitet.

Sei aber vorsichtig hier! Schreiben

Befehl> Datei 2> & 1

ist nicht das Gleiche wie schreiben:

$ Befehl 2> & 1> Datei

Die Reihenfolge der Weiterleitungen ist in Bash wichtig! Dieser Befehl leitet nur die Standardausgabe an die Datei um. Das stderr wird weiterhin auf dem Terminal drucken. Um zu verstehen, warum das passiert, gehen wir noch einmal die Schritte durch. Bevor der Befehl ausgeführt wird, sieht die Dateibeschreibung folgendermaßen aus:

Enter image description here

Jetzt verarbeitet Bash Umleitungen von links nach rechts. Es sieht zuerst 2> & 1, so dass es stderr zu stdout dupliziert. Die Dateibeschreibungstabelle wird zu:

Enter image description here

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

Enter image description here

Siehst du was hier passiert? Stdout zeigt jetzt auf Datei, aber der stderr zeigt immer noch auf das Terminal! Alles, was in stderr geschrieben wird, wird immer noch auf dem Bildschirm ausgedruckt! Also sei sehr, sehr vorsichtig mit der Reihenfolge der Weiterleitungen!

Beachten Sie auch, dass in Bash zu schreiben

$ Befehl &> Datei

ist genau das gleiche wie:

$ Befehl> & Datei


47
2017-10-29 13:04



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


2: "Standart Fehler"Ausgabedatei-Deskriptor.

>&: Duplizieren Sie einen Ausgabedateideskriptor Operator (eine Variante von Ausgabeumleitung Operator >). Gegeben [x]>&[y]der mit. bezeichnete Dateideskriptor x wird zu einer Kopie des Ausgabedateideskriptors gemacht y.

1 "Standardausgabe"Ausgabedatei-Deskriptor.

Der Ausdruck 2>&1 kopiert den Dateideskriptor 1 zum Standort 2, also jede Ausgabe geschrieben 2 ("Standardfehler") in der Ausführungsumgebung geht zu der gleichen Datei, die ursprünglich von beschrieben wurde 1 ("Standardausgabe").


Weitere Erklärung:

Dateibeschreiber: "Eine pro-Prozess eindeutige, nicht negative Ganzzahl, die verwendet wird, um eine geöffnete Datei für den Dateizugriff zu identifizieren."

Standardausgabe / Fehler: Siehe den folgenden Hinweis in der Umleitung Abschnitt 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 heißen "Dateideskriptoren". Die Werte 0, 1 und 2 haben eine besondere Bedeutung und herkömmliche Verwendungen und werden von bestimmten Umleitungsoperationen impliziert; Sie werden als Standardeingabe, Standardausgabe bzw. Standardfehler bezeichnet. Programme nehmen ihre Eingabe normalerweise von der Standardeingabe und schreiben die Ausgabe auf die Standardausgabe. Fehlermeldungen werden normalerweise auf Standardfehler geschrieben. Den Umleitungsoperatoren können eine oder mehrere Ziffern vorangestellt werden (ohne dass dazwischenliegende Zeichen zulässig sind), um die Dateibeschreibernummer zu bestimmen.


13
2017-12-25 06:43



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

Dies ist hilfreich bei "mehr", wenn Paging für alle Ausgaben erforderlich ist. Einige Programme drucken Verwendungsinformationen in stderr.

Um dir zu helfen, dich 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 wird, an stdout an.

Ich empfehle auch, zu lesen Dieser Post bei der Fehlerumleitung wo dieses Thema ausführlich behandelt wird.


12
2018-05-03 23:24