it-swarm.com.de

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

Wenn ich in einer Unix-Shell stderr und stdout zur weiteren Bearbeitung im Stream stdout kombinieren möchte, kann ich am Ende meines Befehls Folgendes anhängen:

2>&1

Wenn ich also head für die 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.

Mir fällt es immer schwer, 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 das aufbrechen und Zeichen für Zeichen erklären, was 2>&1 bedeutet?

2061

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

Hier ist eine Möglichkeit, sich an dieses Konstrukt zu erinnern (obwohl es nicht ganz genau ist): Auf den ersten Blick kann 2>1 eine gute Möglichkeit sein, stderr zu stdout umzuleiten. Tatsächlich wird es jedoch als "stderr in eine Datei mit dem Namen 1 umleiten" interpretiert. & gibt an, dass das Folgende ein Dateideskriptor und kein Dateiname ist. So wird das Konstrukt: 2>&1.

2288
Ayman Hourieh
echo test > afile.txt

leitet stdout zu afile.txt um. Dies ist das gleiche wie das, was Sie tun

echo test 1> afile.txt

Um stderr umzuleiten, tun Sie Folgendes:

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 nach 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 in eine (nicht spezifizierte) Datei um, indem &1 stderr an stdout angehängt wird.

566
dbr

Einige Tricks zur Umleitung

Einige Syntax-Besonderheiten können wichtige Verhaltensweisen haben. Es gibt einige kleine Beispiele für Weiterleitungen, STDERR, STDOUT und Argumente , die die Reihenfolge festlegen.

1 - Überschreiben oder Anhängen?

Symbol _>_ bedeutet Umleitung .

  • _>_ bedeutet Senden an eine vollständige Datei , Überschreiben des Ziels, falls vorhanden (siehe noclobber Bash-Funktion bei # 3 später).
  • _>>_ Mittelwert , der zusätzlich zu gesendet wird, würde an das Ziel angehängt, falls vorhanden.

In jedem Fall wird die Datei erstellt, wenn sie nicht vorhanden ist.

2 - Die Shell Kommandozeile ist auftragsabhängig !!

Um dies zu testen, benötigen wir einen einfachen Befehl, der an beiden Ausgängen 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_;). 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 gibt STDERR an die Konsole aus, und es scheint nicht das erwartete Verhalten zu sein ... Aber ...

Wenn Sie eine Nachfilterung für eine Ausgabe durchführen möchten, für die andere oder für 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 in dem vorherigen Absatz, in dem ich geschrieben habe , scheint nicht das erwartete Verhalten zu sein (dies könnte also sogar ein erwartetes Verhalten sein). .

Nun, es gibt ein paar Tricks zu Umleitungen, um an beiden Ausgängen unterschiedliche Operationen 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
_

Hinweis: _&9_ Deskriptor würde spontan aufgrund von _) 9>&2_ auftreten.

Nachtrag: nota! Mit der neuen Version von bash (_>4.0_) gibt es eine neue Funktion und mehr 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 zum Schluss 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 durchläuft, STDERR einen anderen und schließlich werden beide zusammengeführten Ausgänge durch einen dritten Befehlsfilter geleitet.

3 - Ein Wort zur noclobber -Option und zur _>|_ -Syntax

Das ist ungefähr Überschreiben :

Während _set -o noclobber_ die Bash anweist, keine vorhandenen Dateien zu überschreiben , können Sie mit der _>|_ -Syntax diese Einschränkung umgehen:

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

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

Für die Umleitung beider Ausgaben eines gegebenen Befehls sehen wir, dass eine richtige Syntax sein könnte:

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

für diesen Sonderfall gibt es eine Abkürzungssyntax: _&>_ ... oder _>&_

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

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

Anmerkung: Wenn 2>&1 existiert, 1>&2 ist auch eine korrekte Syntax:

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

4b- Nun lasse ich Sie darüber nachdenken:

_$ 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 mehr Informationen interessiert sind

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

_man -Len -Pless\ +/^REDIRECTION bash
_

in einer bash Konsole ;-)

300
F. Hauri

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

Standardausgabe und Standardfehler in eine Datei umleiten

$ befehl &> datei

Dieser Einzeiler verwendet den Operator &>, um beide Ausgabestreams - stdout und stderr - vom Befehl in die Datei umzuleiten. Dies ist die Abkürzung von Bash, mit der Sie beide Streams schnell an dasselbe Ziel umleiten können.

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

Enter image description here

Wie Sie sehen, zeigen nun sowohl stdout als auch stderr auf file. Also wird alles, was an stdout und stderr geschrieben wurde, an file geschrieben.

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

$ command> file 2> & 1

Dies ist eine 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 Weiterleitungen sieht, werden diese von links nach rechts verarbeitet. Lassen Sie uns die Schritte durchgehen und sehen, wie das passiert. Vor dem Ausführen von Befehlen sieht die Dateideskriptortabelle von Bash folgendermaßen aus:

Enter image description here

Jetzt verarbeitet Bash die erste Umleitungsdatei. Wir haben das schon einmal gesehen und es bringt stdout dazu, zu filen:

Enter image description here

Next Bash sieht 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:

Enter image description here

Beide Streams wurden in die 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! Dieser Befehl leitet nur die Standardausgabe in die Datei um. Das stderr wird weiterhin auf dem Terminal gedruckt. Um zu verstehen, warum das passiert, gehen wir die Schritte noch einmal durch. Vor dem Ausführen des Befehls sieht die Dateideskriptortabelle folgendermaßen aus:

Enter image description here

Jetzt verarbeitet Bash die Weiterleitungen von links nach rechts. Es sieht zuerst 2> & 1, also dupliziert es stderr zu stdout. Die Dateideskriptortabelle wird zu:

Enter image description here

Jetzt sieht Bash die zweite Umleitung, >file, und leitet stdout zur Datei um:

Enter image description here

Sehen Sie, was hier passiert? Stdout zeigt jetzt auf file, aber der stderr zeigt immer noch auf das Terminal! Alles, was an stderr geschrieben wird, wird trotzdem auf dem Bildschirm ausgedruckt! Gehen Sie also sehr, sehr vorsichtig mit der Reihenfolge der Weiterleitungen um!

Beachten Sie auch, dass in Bash, schriftlich

$ befehl &> datei

ist genau das gleiche wie:

$ command> & file

93
Deen John

Die Zahlen beziehen sich auf die Dateideskriptoren (fd).

  • Null ist stdin
  • Einer ist stdout
  • Zwei ist stderr

2>&1 leitet fd 2 zu 1 weiter.

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

Sie können /usr/include/unistd.h anschauen, 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.  */

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

77
Colin Burnett

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

Sie können jedes Ausgabe-Handle mit dieser Methode auf ein anderes umleiten, sie 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 Argument nichtstderr zu outfile2 leitet - es leitet es zu dem um, was stdout war, als das Argument angetroffen wurde (outfile1) und dann leitet stdout zu outfile2 weiter.

Dies erlaubt einige ziemlich ausgefeilte Tricks.

54
paxdiablo

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


2: " Standardfehler " Ausgabedateideskriptor.

>&: Duplizieren eines Ausgabedateideskriptors (eine Variante von Ausgabeumleitung Operator >). Wenn [x]>&[y] gegeben ist, wird der mit x bezeichnete Dateideskriptor als Kopie des Ausgabedateideskriptors y erstellt.

1 " Standardausgabe " Ausgabedateideskriptor.

Der Ausdruck 2>&1 kopiert den Dateideskriptor 1 an den Speicherort 2, sodass alle Ausgaben, die in der Ausführungsumgebung in 2 ("Standardfehler") geschrieben wurden, in dieselbe ursprünglich beschriebene Datei verschoben werden durch 1 ("Standardausgabe").


Weitere Erklärung:

Dateideskriptor : "Eine pro Prozess eindeutige, nicht negative Ganzzahl, die zum Identifizieren einer geöffneten Datei zum Zweck der Datei verwendet wird Zugriff."

Standardausgabe/-fehler : Beachten 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 werden "Dateideskriptoren" genannt. Die Werte 0, 1 und 2 haben eine spezielle 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 auf Standardfehler geschrieben. Den Umleitungsoperatoren können eine oder mehrere Ziffern vorangestellt werden (wobei keine dazwischen liegenden Zeichen zulässig sind), um die Dateideskriptornummer anzugeben.

18
wjordan

2 ist der Konsolenstandardfehler.

1 ist die Standardausgabe der Konsole.

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

Z.B. 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 alle Ausgaben, einschließlich Fehler, in der debug.log sehen.

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

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

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

17
Marcus Thornton

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

Dies ist hilfreich, wenn Sie beispielsweise "mehr" für die gesamte Ausgabe auslagern möchten. Einige Programme drucken beispielsweise Nutzungsinformationen in stderr.

Um Ihnen zu helfen, sich zu erinnern

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

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

Ich empfehle auch das Lesen von dieser Beitrag über die Fehlerumleitung , wo dieses Thema ausführlich behandelt wird.

16
Andrioid

Aus Sicht eines Programmierers bedeutet dies genau Folgendes:

dup2(1, 2);

Siehe Manpage .

Zu verstehen, dass 2>&1 eine 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, der zweite sendet Fehler an stdout und die normale Ausgabe an file.

11
ams

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

$ ls -l /tmp /foo

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

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

sendet den Inhalt von /tmp an /dev/null und 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 /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

6
Matijs

Leute, denkt immer an den Hinweis von paxdiablo über die aktuelle Position des Umleitungsziels ... Es ist wichtig.

Meine persönliche Kurzbezeichnung für den Operator 2>&1 lautet:

  • Stellen Sie sich & als 'and' oder 'add' vor (das Zeichen ist ein Amper - und , nicht wahr?)
  • So wird es: 'umleiten 2 (stderr) zu wo 1 (stdout) bereits/aktuell ist und add beide Streams' .

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

  • Denken Sie an &, was and oder add bedeutet ... (Sie haben die Idee über das kaufmännische Und, ja?)
  • So wird es: 'umleiten 1 (stdout) zu wo 2 (stderr) bereits/aktuell ist und add beide Streams' .

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

6
Kurt Pfeifle

Dies ist so, als würde man den Fehler an die Standardausgabe oder das Terminal weitergeben.

Das heißt, cmd ist kein Befehl:

$cmd 2>filename
cat filename

command not found

Der Fehler wird folgendermaßen an die Datei gesendet:

2>&1

Standardfehler wird an das Terminal gesendet.

5
Kalanidhi

Eingabe umleiten

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

Das allgemeine Format zum Umleiten von Eingaben lautet:

[n]<Word

Ausgabe umleiten

Die Umleitung der Ausgabe bewirkt, dass die Datei, deren Name sich aus der Erweiterung von Word ergibt, zum Schreiben in den Dateideskriptor n oder in 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 die Größe Null gekürzt.

Das allgemeine Format zum Umleiten 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 Dateideskriptor-Ziffer in den Dateideskriptor n oder in die Standardausgabe (Dateideskriptor 1), wenn n nicht angegeben ist.

Ref:

man bash

Geben Sie /^REDIRECT ein, um zum Abschnitt redirection zu gelangen, und erfahren Sie mehr ...

Eine Online-Version finden Sie hier: .6 Weiterleitungen

PS:

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

4
yurenchen

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

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

1
fzyzcjy