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

Wenn ich in einer Unix-Shell stderr und stdout in den stdout-Stream für weitere Manipulationen zusammenfassen möchte, kann ich am Ende meines Befehls folgendes anhängen:

2>&1

Wenn ich also head auf die Ausgabe von g++ anwenden möchte, kann ich etwas wie folgt tun:

g++ lots_of_errors 2>&1 | head

damit ich nur die ersten paar Fehler sehen kann.

Ich habe immer Schwierigkeiten, mir das zu merken, und muss ständig nachschlagen, und das liegt vor allem daran, dass ich die Syntax dieses speziellen Tricks nicht ganz verstehe.

Kann mir jemand das aufschlüsseln und Zeichen für Zeichen erklären, was 2>&1 bedeutet?

Lösung

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

Hier ist eine Möglichkeit, sich dieses Konstrukt zu merken (obwohl es nicht ganz korrekt ist): auf den ersten Blick mag 2>1 wie ein guter Weg aussehen, stderr nach stdout umzuleiten. Es wird jedoch tatsächlich als "leite stderr zu einer Datei namens 1 um" interpretiert. Das "&" zeigt an, dass es sich bei dem, was folgt, um einen Dateideskriptor und nicht um einen Dateinamen handelt. Also wird das Konstrukt zu: 2>&1.

Kommentare (18)
echo test > afile.txt

leitet stdout nach afile.txt um. Dies ist dasselbe wie die Ausführung von

echo test 1> afile.txt

Um stderr umzuleiten, tun Sie das:

echo test 2> afile.txt

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

Sie können stdout nach stderr umleiten, indem Sie dies tun:

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

Oder andersherum:

echo test 2>&1

Also, kurz gesagt... 2> leitet stderr zu einer (nicht spezifizierten) Datei um, das Anhängen von &1 leitet stderr zu stdout um.

Kommentare (5)

Die Zahlen beziehen sich auf die Dateideskriptoren (fd).

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

2>&1" leitet fd 2 auf 1 um.

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

Sie können in /usr/include/unistd.h nachsehen, wenn Sie sie vergessen haben:

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

Davon abgesehen habe ich C-Tools geschrieben, die nicht-standardisierte Dateideskriptoren für benutzerdefinierte Protokollierung verwenden, so dass man sie nicht sieht, es sei denn, man leitet sie in eine Datei oder so um.

Kommentare (0)