In der shell, was bedeutet "2>&1" mean?
Frage
In einer Unix-shell, wenn ich will, zu verbinden stderr
und stdout
in der stdout
stream für die weitere manipulation, die ich Anhängen können, die folgenden am Ende von mein Befehl:
2>&1
Also, wenn ich verwenden möchten head
auf die Ausgabe von g++
, Kann ich so etwas wie dies tun:
g++ lots_of_errors 2>&1 | head
so kann ich sehen, nur die ersten paar Fehler.
Ich habe immer Schwierigkeiten haben, zu erinnern, und ich muss ständig nachschlagen, und es ist vor allem, weil ich nicht vollständig verstehen, die syntax dieses besonderen trick.
Kann jemand brechen diese auf und erklären, Zeichen von dem, was 2>&1
bedeutet?
Lösung
File Descriptor 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): Zunächst 2>1
wie ein guter Weg aussehen kann stderr
umleiten stdout
. Allerdings wird es tatsächlich als „Redirect stderr
in einer Datei namens 1
“ interpretiert werden. &
zeigt an, dass, was folgt ein Dateideskriptor ist und kein Dateiname. So das Konstrukt wird. 2>&1
Andere Tipps
echo test > afile.txt
leitet stdout afile.txt
. Dies ist das gleiche wie zu tun
echo test 1> afile.txt
So leiten stderr, was Sie tun:
echo test 2> afile.txt
>&
ist die Syntax eines Stroms an einen anderen Dateideskriptor zu umleiten - 0 ist stdin, 1 ist stdout und 2 ist Stderr
Sie können stdout zu stderr umleiten, indem Sie:
echo test 1>&2 # or echo test >&2
Oder umgekehrt:
echo test 2>&1
Also, kurz gesagt ... 2>
leitet stderr auf eine (nicht näher bezeichnet) Datei, &1
anhängt stderr nach stdout umleitet.
Einige tricks zu Umleitung
Die syntax der Besonderheit, über diesen können wichtige Verhaltensweisen.Es gibt einige kleine Proben über Umleitungen STDERR
, STDOUT
, und Argumente Bestellung.
1 - Überschreiben oder Anhängen?
Symbol >
bedeuten Umleitung.
>
bedeuten senden als ganzes abgeschlossen Datei, überschreiben Ziel, wenn vorhanden (siehenoclobber
bash-Funktion zu #3 später).>>
bedeuten senden Sie zusätzlich zu würde anfügen Ziel, wenn vorhanden.
In jedem Fall würde die Datei erstellt, falls Sie nicht existieren.
2 - Die shell-Befehlszeile ist, um abhängig!!
Um dieses zu testen, müssen wir ein einfacher Befehl senden etwas auf beide Ausgänge:
$ 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
(Erwarten Sie nicht haben ein Verzeichnis mit dem Namen /tnt
, natürlich ;).Nun, wir haben es!!
Also, lasst uns 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
Der Letzte Befehl-Linie dumps STDERR
auf der Konsole, und es scheint nicht das zu erwartende Verhalten...Aber...
Wenn Sie wollen einige post-Filterung über einen Ausgang, der 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 ist genau das gleiche wie im vorherigen Absatz, wo ich schrieb nicht das erwartete Verhalten (ja, diese könnte sogar ein erwartetes Verhalten).
Nun, da gibt es kleine tricks, über Umleitungen, für anders macht-Betrieb auf beide Ausgänge:
$ ( 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
descriptor würde spontan auftreten aufgrund von ) 9>&2
.
Nachtrag:nota! Mit der neuen version von bash (>4.0
) es gibt ein neues feature und mehr sexy syntax für diese Art der Dinge:
$ 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 Kaskadierung Ausgabe:
$ ((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! Gleichen neue syntax, die in beide 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
Wo STDOUT
gehen durch eine Besondere filter, STDERR
zum anderen, und schließlich werden beide Ausgänge zusammengeführt gehen durch eine Dritte Befehl filter.
3 - Ein Wort über noclobber
option und >|
syntax
Das ist über überschreiben:
Während set -o noclobber
anweisen-bash zu nicht vorhandene Dateien überschreiben, die >|
syntax können Sie die über diese Beschränkung:
$ 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, nun:
$ 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-through 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
Entfernen Sie diese option und/oder fragte, ob schon 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 - Letzten Stich und mehr...
Für das umleiten beide Ausgabe von einem Befehl gegeben, sehen wir, dass eine richtige syntax wäre:
$ ls -ld /tmp /tnt >/dev/null 2>&1
für diese Besondere Fall, gibt es einen shortcut syntax: &>
...oder >&
$ ls -ld /tmp /tnt &>/dev/null
$ ls -ld /tmp /tnt >&/dev/null
Nota:wenn 2>&1
existieren, 1>&2
ist eine korrekte syntax zu:
$ ls -ld /tmp /tnt 2>/dev/null 1>&2
4b - Nun, ich lasse Sie denken:
$ 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 in mehr Informationen
Sie könnte Lesen Sie das Handbuch durch das schlagen:
man -Len -Pless\ +/^REDIRECTION bash
in einem bash Konsole ;-)
Ich fand diese brillante Post auf Umleitung: alles über Umleitungen
Umleiten sowohl die Standardausgabe und Standardfehler in eine Datei
$ command &> Datei
Dieser Einzeiler verwendet die &>
Bediener beiden Ausgangsströme zu umleiten - stdout und stderr - von Befehl Datei. Dies ist Abkürzung des Bash für schnell beiden Ströme zum gleichen Ziel umgeleitet werden.
Hier ist, wie die Datei Deskriptortabelle sieht aus wie nach Bash beiden Strömen wird umgeleitet:
Wie Sie sehen können, sowohl stdout und stderr jetzt file
zeigen. So etwas geschrieben zu stdout und stderr wird auf file
geschrieben.
Es gibt mehr Möglichkeiten, beiden Ströme zum gleichen Ziel zu umleiten. Sie können jeden Strom umleiten nacheinander:
$ command> Datei 2> & 1
Dies ist ein sehr viel häufiger Weg, um beiden Ströme in eine Datei zu umleiten. Erste stdout wird umgeleitet in Datei, und dann wird Stderr dupliziert die gleichen wie stdout zu sein. Also beiden Ströme zeigen am Ende file
.
Wenn Bash mehrere Umleitungen sieht es verarbeitet sie von links nach rechts. Lassen Sie uns die Schritte durchgehen und sehen, wie das passiert. Vor dem Ausführen wie dies alle Befehle, Bash Dateideskriptors Tabelle aussieht:
Jetzt Bash verarbeitet die erste Umleitung> Datei. Wir haben dies gesehen und es macht stdout Punkt in Datei:
Als nächstes Bash sieht die zweite Umleitung 2> & 1. Wir haben diese Umleitung nicht gesehen. Dieser dupliziert 2 Dateideskriptors eine Kopie von Dateideskriptor zu 1 und wir erhalten:
Beide Ströme wurden umgeleitet Datei.
Jedoch vorsichtig sein, hier! Schreiben
Befehl> Datei 2> & 1
ist nicht das gleiche wie das Schreiben:
$ command 2> & 1> Datei
Die Reihenfolge der Umleitungen Angelegenheiten in Bash! Dieser Befehl leitet nur die Standardausgabe in die Datei. Die stderr wird noch an das Terminal drucken. Um zu verstehen, warum das passiert, lassen Sie uns noch einmal die Schritte durchlaufen. Also, bevor der Befehl ausgeführt wird, der Dateideskriptor Tabelle sieht wie folgt aus:
Jetzt verarbeitet Bash Umleitungen links nach rechts. Es sieht zunächst 2> & 1 so dupliziert es stderr nach stdout. Die Datei Deskriptortabelle wird:
Jetzt Bash sieht die zweite Umleitung, >file
, und es leitet stdout in Datei:
Sehen Sie, was hier geschieht? Stdout verweist nun auf Datei, aber die stderr immer noch auf dem Terminal! Alles, was auf stderr geschrieben wird nach wie vor wird auf dem Bildschirm ausgedruckt! So sehr, sehr vorsichtig mit der Reihenfolge der Umleitungen!
Beachten Sie auch, dass in Bash, Schreiben
$ commund &> Datei
ist genau das gleiche wie:
$ command> & Datei
Die Zahlen beziehen sich auf die Datei-Deskriptoren (fd).
- Zero ist
stdin
- Eine davon ist
stdout
- Zwei ist
stderr
2>&1
umleitet fd 2 bis 1.
Dies funktioniert für eine beliebige Anzahl von Datei-Deskriptoren, wenn das Programm verwendet sie.
Sie können an /usr/include/unistd.h
aussehen, wenn man sie vergessen:
/* Standard file descriptors. */
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
Wie gesagt ich C-Tools geschrieben, das Nicht-Standard-Dateibeschreibungen für benutzerdefinierte Protokollierung verwenden, so dass Sie es nicht sehen, wenn Sie es in eine Datei oder etwas umgeleitet werden.
Das Konstrukt sendet den Standard-Fehlerstrom (stderr
) zu dem Strom Lage der Standardausgabe (stdout
.) - diese Währung Problem scheint von den anderen Antworten vernachlässigt worden zu sein
Sie können eine beliebige Ausgabehandle auf eine andere umleiten, indem Sie diese Methode verwenden, aber es ist am häufigsten auf Kanal stdout
verwendet und stderr
Ströme in einen einzigen Strom 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 direkt stderr
outfile2
- es leitet es automatisch zu, was stdout
war, als das Argument angetroffen wurde (outfile1
) und und Umleitungen stdout
outfile2
.
Auf diese Weise können einige ziemlich anspruchsvolle Tricks.
2>&1
ist ein POSIX-Shell-Konstrukt. Hier ist eine Auflistung, Token Token:
2
:. " Standardfehler " -Ausgang Dateideskriptor
>&
: Duplizieren ein Output File Descriptor Operator (eine Variante von Ausgabe Umleitung Betreiber >
). In Anbetracht [x]>&[y]
, der Dateideskriptor durch x
bezeichnet wird eine Kopie der Ausgabe Dateideskriptors y
sein.
1
" Standardausgabe " -Ausgang Dateideskriptor.
Der Ausdruck 2>&1
Kopien Dateideskriptors 1
an Ort 2
, so dass jede Ausgabe geschrieben 2
( „Standardfehler“) in der Ausführungsumgebung geht auf die gleiche Datei ursprünglich von 1
beschrieben ( „Standardausgabe“).
Eine weitere Erklärung:
Dateideskriptor : „Ein pro-Prozess einzigartig, nicht negative ganze Zahl verwendet, um eine offene Datei zum Zweck der Dateizugriff zu identifizieren.“
Standard-Ausgang / Fehler : Siehe folgende Notiz in der Redirection Bereich der Shell-Dokumentation:
Öffnen von Dateien werden durch Dezimalzahlen dargestellt beginnend mit Null. Der größtmögliche Wert ist die Implementierung definiert; jedoch alle Implementierungen müssen mindestens 0 bis 9, einschließlich, für die Nutzung durch die Anwendung unterstützen. Diese Zahlen werden als „Datei-Deskriptoren“ bezeichnet. Die Werte 0, 1 und 2 haben eine besondere Bedeutung und herkömmliche Anwendungen und werden durch bestimmte Umleitung Operationen impliziert; sie werden als Standardeingabe, Standardausgabe bezeichnet und Standardfehler sind. Programme dauern in der Regel ihre Eingabe von der Standardeingabe und Ausgabe auf der Standardausgabe schreiben. Fehlermeldungen werden in der Regel auf dem Standardfehler geschrieben. Die Umleitungsoperator können durch eine oder mehr Ziffern vorangestellt werden (ohne dazwischenliegende Zeichen erlaubt) die Dateideskriptor Nummer zu bezeichnen.
2 ist die Konsole Standardfehler.
1 ist die Konsole Standard-Ausgabe.
Dies ist das Standard-Unix und Windows folgt auch die POSIX.
z. beim Ausführen
perl test.pl 2>&1
der Standardfehler wird auf der Standardausgabe umgeleitet, so dass Sie beiden Ausgänge zusammen sehen:
perl test.pl > debug.log 2>&1
Nach der Ausführung können Sie alle Ausgaben sehen, einschließlich Fehler, im debug.log.
perl test.pl 1>out.log 2>err.log
Dann Standardausgabe geht auf out.log und Standardfehler auf err.log.
Ich schlage vor, Sie zu versuchen, diese zu verstehen.
Um Ihre Frage zu beantworten: Es dauert einen Fehler Ausgang (normalerweise an stderr gesendet) und schreibt sie auf der Standardausgabe (stdout).
Dies ist hilfreich, mit zum Beispiel ‚mehr‘, wenn Sie benötigen Paging für alle Ausgaben. Einige Programme wie das Drucken Nutzungsinformationen in stderr.
Damit Sie merken
- 1 = Standardausgabe (wo Programme normale Ausgabe drucken)
- 2 = Standardfehler (wo Programme Druckfehler)
"2> & 1" einfach Punkte, alles zu stderr, schickte statt nach stdout.
Ich empfehle auch diesen Beitrag auf Fehler beim Lesen der Umleitung wo diese Thema wird ausführlich behandelt.
Von einem Programmierer Sicht, bedeutet genau das:
dup2(1, 2);
Sehen Sie die Manpage .
, dass 2>&1
zu verstehen, ist eine Kopie auch erklärt, warum ...
command >file 2>&1
... ist nicht das gleiche wie ...
command 2>&1 >file
Die erste wird beiden Ströme senden file
, während die zweiten Fehler sendet an stdout
und gewöhnliche Ausgabe in file
.
Menschen, immer daran denken, paxdiablo 's Hinweis auf die Strom Standort des Umleitungsziel ... Es ist wichtig.
Meine persönliche mnemonic für den 2>&1
Betreiber ist dies:
- Denken Sie an
&
dahin'and'
oder'add'
(das Zeichen ein ampers - und , ist es nicht) - So wird es. 'umleiten
2
(stderr), wo1
(stdout) bereits / aktuell ist und hinzufügen beiden Ströme'
Die gleichen mnemonic Arbeiten für die andere häufig verwendete Umleitung auch 1>&2
:
- Denken Sie an
&
Bedeutungand
oderadd
... (Sie auf die Idee über den Ampersand zu bekommen, nicht wahr?) - So wird es. 'umleiten
1
(stdout), wo2
(stderr) bereits / aktuell ist und hinzufügen beiden Ströme'
Und immer daran denken: Sie haben Ketten von Umleitungen lesen ‚vom Ende‘, von rechts nach links ( nicht von links nach rechts)
. Sofern /foo
nicht auf Ihrem System vorhanden ist und /tmp
tut ...
$ ls -l /tmp /foo
wird der Inhalt von /tmp
drucken und eine Fehlermeldung für /foo
drucken
$ ls -l /tmp /foo > /dev/null
wird der Inhalt von /tmp
senden Sie eine Fehlermeldung für /dev/null
/foo
und drucken
$ ls -l /tmp /foo 1> /dev/null
wird genau das gleiche tun (beachten Sie die 1 )
$ ls -l /tmp /foo 2> /dev/null
wird der Inhalt von /tmp
drucken und die Fehlermeldung senden an /dev/null
$ ls -l /tmp /foo 1> /dev/null 2> /dev/null
wird sowohl die Liste als auch die Fehlermeldung senden an /dev/null
$ ls -l /tmp /foo > /dev/null 2> &1
ist eine Abkürzung
Das ist wie der Fehler an den stdout oder den Terminal übergeben.
Das heißt, cmd
ist kein Befehl:
$cmd 2>filename
cat filename
command not found
Der Fehler wird in die Datei wie folgt gesendet:
2>&1
Standardfehler werden an das Terminal gesendet.
Umleiten Eingang
Umleitung des Eingangs bewirkt, dass die Datei, deren Name ergibt sich aus der Expansion des Wortes zum Lesen auf Datei geöffnet werden Deskriptors n oder die Standardeingabe (Dateideskriptor 0), wenn n nicht angegeben.
Das allgemeine Format für die Eingabe Umleitung ist:
[n]<word
Umleiten Ausgabe
Umleitung von Ausgang bewirkt, dass die Datei, deren Name ergibt sich aus der Expansion des Wortes zum Schreiben auf geöffnet werden Dateideskriptor n, oder die Standardausgabe (Dateideskriptor 1), wenn n ist nicht angegeben. Wenn die Datei nicht existiert erstellt; wenn es existiert es auf die Größe Null gekürzt wird.
Das allgemeine Format für die Ausgabe Umleitung ist:
[n]>word
Umzug Filedeskriptoren
Der Umleitungsoperator,
[n]<&digit-
verschiebt den einstelligen Dateideskriptors den Dateideskriptor n oder Standardeingabe (Dateideskriptor 0), wenn n nicht angegeben ist. Ziffer wird geschlossen, nachdem n dupliziert werden.
Auch der Umleitungsoperator
[n]>&digit-
verschiebt den einstelligen Dateideskriptors den Dateideskriptor n oder Standardausgabe (Dateideskriptor 1), wenn n nicht angegeben ist.
Ref:
man bash
Typ /^REDIRECT
zum redirection
Abschnitt zu finden, und erfahren Sie mehr ...
Eine Online-Version ist hier: 3.6 Umleitungen
PS:
Viele der Zeit war man
das mächtige Werkzeug, um Linux zu lernen.
0 für Eingang, 1 für stdout und 2 für stderr.
Ein Tipp: :
somecmd >1.txt 2>&1
richtig ist, während somecmd 2>&1 >1.txt
ist total falsch ohne Wirkung!