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?

War es hilfreich?

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 (siehe noclobber 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 (>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 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:

 Gib Bild Beschreibung hier

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:

 Gib Bild Beschreibung hier

Jetzt Bash verarbeitet die erste Umleitung> Datei. Wir haben dies gesehen und es macht stdout Punkt in Datei:

 Gib Bild Beschreibung hier

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:

 Gib Bild Beschreibung hier

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:

 Gib Bild Beschreibung hier

Jetzt verarbeitet Bash Umleitungen links nach rechts. Es sieht zunächst 2> & 1 so dupliziert es stderr nach stdout. Die Datei Deskriptortabelle wird:

 Gib Bild Beschreibung hier

Jetzt Bash sieht die zweite Umleitung, >file, und es leitet stdout in Datei:

 Gib Bild Beschreibung hier

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), wo 1 (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 & Bedeutung and oder add ... (Sie auf die Idee über den Ampersand zu bekommen, nicht wahr?)
  • So wird es. 'umleiten 1 (stdout), wo 2 (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!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top