www - in bash inserting 2>& 1 after a command redirects




Was bedeutet in der Shell "2> & 1"? (10)

Wenn ich in einer Unix-Shell stderr und stdout zur weiteren Bearbeitung in den stdout Stream integrieren möchte, kann ich am Ende meines Befehls folgendes hinzufügen:

2>&1

Also, wenn ich "Kopf" auf der Ausgabe von g ++ verwenden möchte, kann ich etwas tun:

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 Buchstabe erklären, was "2> & 1" bedeutet?


Umleitung der Eingabe

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

Das allgemeine Format zum Umleiten von Eingaben ist:

      [n]<word

Ausgabe umleiten

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

Das allgemeine Format zum Umleiten von Ausgaben ist:

      [n]>word

Verschieben von Dateideskriptoren

Verschieben von Dateideskriptoren Der Umleitungsoperator

      [n]<&digit-

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

In ähnlicher Weise der Umleitungsoperator

      [n]>&digit-

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

Ref:

man bash
/^REDIRECT , um zum redirection Weitere /^REDIRECT

eine Online-Version hier:
http://www.gnu.org/software/bash/manual/bashref.html#Redirections

ps:

viel Zeit, der man war das mächtige Werkzeug, um Linux zu lernen


Einige Tricks zur Umleitung

Einige Besonderheiten der Syntax können wichtige Verhaltensweisen haben. Es gibt einige kleine Beispiele über Umleitungen, STDERR , STDOUT und die Reihenfolge der Argumente.

1 - Überschreiben oder anhängen?

Symbol > mittlere Umleitung .

  • > mean send an als Ganzes abgeschlossene Datei , Überschreiben Ziel, wenn vorhanden (siehe noclobber Bash Feature an # 3 später).
  • >> bedeuten senden zusätzlich zu würde an Ziel anhängen, wenn vorhanden.

Jedenfalls würde die Datei erstellt, wenn sie nicht existiert.

2 - Die Kommandozeile der Shell ist auftragsabhängig !!

Um dies zu testen, benötigen wir einen einfachen 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

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

Also sehen wir:

$ 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 Kommandozeile dump STDERR an die Konsole, es scheint nicht das erwartete Verhalten zu sein ... Aber ...

Wenn Sie eine Post-Filterung um eine Ausgabe machen wollen, die andere 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 ist wie im vorherigen Paragraph, wo ich geschrieben habe , dass dies nicht das erwartete Verhalten ist (dies könnte sogar ein erwartetes Verhalten sein).

Nun, es gibt ein paar Tricks über Umleitungen, um verschiedene Operationen an beiden Ausgaben auszufü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: &9 Deskriptor würde spontan auftreten wegen ) 9>&2 .

Nachtrag: NOTA! Mit der neuen Version von bash ( >4.0 ) gibt es 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 STDOUT einen bestimmten Filter durchlaufen, wird STDERR zu einem anderen und schließlich beide zusammengeführt durch einen dritten Befehlsfilter gehen.

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

Das ist Überschreiben :

Während set -o noclobber bash anweist, keine vorhandene Datei zu überschreiben, wird 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

Mit >| durchgehen :

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

Um die Ausgabe von einem gegebenen 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 Abkürzungssyntax: &> ... oder >&

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

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

Anmerkung: Wenn 2>&1 existiert, ist 1>&2 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 an weiteren Informationen interessiert sind

Sie könnten das Fine Manual lesen, indem Sie:

man -Len -Pless\ +/^REDIRECTION bash

in einer bash Konsole ;-)


2 ist der Standardfehler der Konsole.

1 ist die Konsolen-Standardausgabe.

Dies ist der Standard Unix, 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 debug.log sehen.

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

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

Ich schlage vor, Sie versuchen, diese zu verstehen.


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 korrekt ist): Zunächst sieht 2>1 wie eine gute Möglichkeit aus, stderr auf stdout umzuleiten. Es wird jedoch tatsächlich als "Umleitung stderr zu einer Datei mit dem Namen 1 " interpretiert. & zeigt an, dass ein Dateideskriptor und kein Dateiname folgt. So wird das Konstrukt: 2>&1 .


Dies ist genau so, als würde der Fehler auf dem Stdout oder Terminal terminiert werden. dh. cmd ist kein Befehl $ cmd 2> Dateiname cat Dateiname Befehl nicht gefunden

Der an die Datei gesendete Fehler 2> & 1 Fehler an das Terminal gesendet


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 ein beliebiges Ausgabe-Handle in ein anderes umleiten, es wird jedoch am häufigsten verwendet, um stdout und stderr Streams zur Verarbeitung in einen einzelnen Stream zu leiten.

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 stderr zu outfile2 leitet - es leitet es an die stdout um, als das Argument gefunden wurde ( outfile1 ), und leitet dann stdout nach outfile2 .

Dies ermöglicht einige ziemlich raffinierte Tricks.


Ich fand diesen brillanten Beitrag zur Weiterleitung: Alles über Weiterleitungen

Leiten Sie die Standardausgabe und den Standardfehler in eine Datei um

$ Befehl &> Datei

Dieser Einzeiler verwendet den Operator &>, um beide Ausgabeströme - stdout und stderr - von Befehl zu Datei umzuleiten. Dies ist die Bash-Verknüpfung zum schnellen Umleiten beider Streams an dasselbe Ziel.

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

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

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. Beide Streams zeigen also auf Datei.

Wenn bash mehrere Umleitungen sieht, werden sie von links nach rechts verarbeitet. Lass uns durch die Schritte gehen und sehen, wie das passiert. Vor dem Ausführen von Befehlen sieht die Dateideskriptortabelle von bash wie folgt aus:

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

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:

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 Redirects ist wichtig in bash! 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. Vor dem Ausführen des Befehls sieht die Dateibeschreibungstabelle folgendermaßen aus:

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

Jetzt sieht bash die zweite redirect> Datei und leitet stdout in Datei um:

Siehst du was hier passiert? Stdout zeigt nun 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, dies zu schreiben:

$ Befehl &> Datei

Ist genau das Gleiche wie:

$ Befehl> & Datei


Leute, erinnern Sie sich immer an den Hinweis von Paxdiablo über den aktuellen Standort des Umleitungsziels ... Es ist wichtig.

Meine persönliche Gedächtnisstütze für den Operator 2>&1 lautet wie folgt:

  • Denken Sie an & als Bedeutung 'and' oder 'add' (der Charakter ist ein Ampere - und , nicht wahr ?)
  • So wird es: "redirect 2 (stderr) zu wo 1 (stdout) bereits / aktuell ist und beide streams" .

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

  • Denken Sie an & Bedeutung and oder add Sie add ... (Sie bekommen die Idee über das kaufmännische Und, ja?)
  • So wird es: "redirect 1 (stdout) zu wo 2 (stderr) bereits / zZ ist und addieren beide Ströme" .

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


Vorausgesetzt, dass /foo auf Ihrem System nicht existiert und /tmp ...

$ ls -l /tmp /foo

druckt den Inhalt von /tmp und gibt eine Fehlermeldung für /foo

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

sendet den Inhalt von /tmp an /dev/null und gibt eine Fehlermeldung für /foo

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

werde genau das gleiche machen (beachte die 1 )

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

Druckt den Inhalt von /tmp und 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 Kurzschrift


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

2 : " Standardfehler " Ausgabedateideskriptor.

>& : Duplizieren Sie einen Ausgabedatei-Deskriptor- Operator (eine Variante des Output Redirection- Operators > ). Mit [x]>&[y] wird der mit x bezeichnete Dateideskriptor als eine Kopie des Ausgabedateideskriptors y .

1 Ausgabedateideskriptor " Standardausgabe ".

Der Ausdruck 2>&1 kopiert den Dateideskriptor 1 an den Speicherort 2 , so dass jede in der Ausführungsumgebung auf 2 geschriebene Ausgabe ("Standardfehler") in dieselbe ursprünglich mit 1 beschriebene Datei geht ("Standardausgabe").

Weitere Erklärung:

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

Standardausgabe / -fehler : Lesen Sie den folgenden Hinweis im Abschnitt Redirection 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.





redirect