Wie leite ich stdout und stderr um und hänge sie an eine Datei mit Bash an?

1533

Um stdout in eine abgeschnittene Datei in Bash umzuleiten , muss ich Folgendes verwenden:

cmd > file.txt

Um stdout in Bash umzuleiten und an eine Datei anzuhängen, muss ich Folgendes verwenden:

cmd >> file.txt

Um sowohl stdout als auch stderr in eine abgeschnittene Datei umzuleiten , muss ich Folgendes verwenden:

cmd &> file.txt

Wie leite ich sowohl stdout als auch stderr um , die an eine Datei angehängt werden? cmd &>> file.txthat bei mir nicht funktioniert.

Flybywire
quelle
37
Ich möchte darauf hinweisen, dass &> outfile ein Bash (und andere) spezifischer Code ist und nicht portabel. Der Weg, portabel zu werden (ähnlich wie die anhängenden Antworten) war und ist immer> outfile 2> & 1
TheBonsai

Antworten:

1998
cmd >>file.txt 2>&1

Bash führt die Weiterleitungen von links nach rechts wie folgt aus:

  1. >>file.txt: file.txtIm Append-Modus öffnen und dort umleiten stdout.
  2. 2>&1: Weiterleiten stderrzu "wohin stdoutgeht es gerade" . In diesem Fall handelt es sich um eine Datei, die im Anhänge-Modus geöffnet wurde. Mit anderen Worten, das &1verwendet den stdoutaktuell verwendeten Dateideskriptor wieder.
Alex Martelli
quelle
33
funktioniert super! Aber gibt es eine Möglichkeit, dies zu verstehen, oder sollte ich dies wie ein atomares Bash-Konstrukt behandeln?
Flybywire
181
Es ist eine einfache Umleitung. Umleitungsanweisungen werden wie immer von links nach rechts ausgewertet. >> Datei: Rot. STDOUT zur Datei (Append-Modus) (kurz für 1 >> Datei) 2> & 1: Rot. STDERR zu "wohin stdout geht" Beachten Sie, dass die Interpretation "STDERR zu STDOUT umleiten" falsch ist.
TheBonsai
31
Es heißt "Ausgabe (stdout, Dateideskriptor 1) an file.txt anhängen und stderr (Dateideskriptor 2) an dieselbe Stelle wie fd1 senden".
Bis auf weiteres angehalten.
2
@TheBonsai aber was ist, wenn ich STDERR in eine andere Datei umleiten muss, aber anhängen muss? Ist das möglich?
Arod
41
Wenn Sie dies tun cmd >>file1 2>>file2, sollte es das erreichen, was Sie wollen.
Woodrow Douglass
367

Abhängig von Ihrer Bash-Version gibt es zwei Möglichkeiten, dies zu tun.

Der klassische und tragbare Weg ( Bash Pre-4 ) ist:

cmd >> outfile 2>&1

Ein nicht portabler Weg, beginnend mit Bash 4, ist

cmd &>> outfile

(analog zu &> outfile)

Für einen guten Codierungsstil sollten Sie

  • Entscheiden Sie, ob Portabilität ein Problem darstellt (verwenden Sie dann den klassischen Weg).
  • Entscheiden Sie, ob die Portabilität auch auf Bash Pre-4 ein Problem darstellt (verwenden Sie dann den klassischen Weg).
  • Egal welche Syntax Sie verwenden, ändern Sie sie nicht innerhalb desselben Skripts (Verwirrung!)

Wenn Ihr Skript bereits mit beginnt #!/bin/sh(egal ob beabsichtigt oder nicht), ist die Bash 4-Lösung und im Allgemeinen jeder Bash-spezifische Code nicht der richtige Weg.

Denken Sie auch daran, dass Bash 4 &>>nur eine kürzere Syntax ist - es werden keine neuen Funktionen oder ähnliches eingeführt.

Die Syntax wird (neben anderer Umleitungssyntax) hier beschrieben: http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output

TheBonsai
quelle
8
Ich bevorzuge & >>, da es mit &> und >> übereinstimmt. Es ist auch einfacher zu lesen, "Ausgabe und Fehler an diese Datei anhängen" als "Fehler an Ausgabe senden, Ausgabe an diese Datei anhängen". Hinweis: Während Linux im Allgemeinen eine aktuelle Version von Bash hat, erfordert OS X zum Zeitpunkt des Schreibens immer noch, dass Bash 4 manuell über Homebrew usw. installiert wird.
mikemaccana
Ich mag es mehr, weil es kürzer ist und nur zwei Stellen pro Zeile enthält. Was würde also zsh aus "& >>" machen?
Phillipp
Es ist auch wichtig zu beachten, dass Sie in einem Cron-Job die Pre-4-Syntax verwenden müssen, auch wenn Ihr System Bash 4 hat.
Hyperknot
5
@zsero cron verwendet bash überhaupt nicht ... es verwendet sh. Sie können die Standard-Shell ändern SHELL=/bin/bash, indem Sie der crontab -eDatei ein Präfix voranstellen .
Ray Foss
89

In Bash können Sie Ihre Weiterleitungen zu verschiedenen Dateien auch explizit angeben:

cmd >log.out 2>log_error.out

Das Anhängen wäre:

cmd >>log.out 2>>log_error.out
Aaron R.
quelle
6
Wenn Sie zwei Streams mit Ihrer ersten Option in dieselbe Datei umleiten, schreibt der erste "über" den zweiten und überschreibt einen Teil oder den gesamten Inhalt. Verwenden Sie stattdessen cmd >> log.out 2> log.out .
Orestis P.
3
Danke, dass du das verstanden hast. du hast recht, einer wird den anderen verprügeln. Ihr Befehl funktioniert jedoch auch nicht. Ich denke, die einzige Möglichkeit, in dieselbe Datei zu schreiben, ist die zuvor angegebene cmd >log.out 2>&1. Ich bearbeite meine Antwort, um das erste Beispiel zu entfernen.
Aaron R.
65

In Bash 4 (sowie ZSH 4.3.11):

cmd &>>outfile

nur aus der Box

AB
quelle
2
@all: Dies ist eine gute Antwort, da es mit Bash funktioniert und kurz ist. Deshalb habe ich es bearbeitet, um sicherzustellen, dass Bash explizit erwähnt wird.
Mikemaccana
10
@mikemaccana: Die Antwort von TheBonsai zeigt bash 4 Lösung seit 2009
jfs
52

Dies sollte gut funktionieren:

your_command 2>&1 | tee -a file.txt

Alle Protokolle werden in file.txt gespeichert und auf dem Terminal gespeichert .

Pradeep Goswami
quelle
Dies ist die richtige Antwort, wenn Sie die Ausgabe auch im Terminal sehen möchten. Dies war jedoch nicht die ursprünglich gestellte Frage.
Mikko Rantalainen
25

Versuche dies

You_command 1>output.log  2>&1

Ihre Verwendung von &> x.file funktioniert in bash4. das tut mir leid : (

Hier kommen einige zusätzliche Tipps.

0, 1, 2 ... 9 sind Dateideskriptoren in bash.

0 steht für stdin, 1 steht für stdout, 2 steht für stderror. 3 ~ 9 ist für jede andere vorübergehende Verwendung frei.

Jeder Dateideskriptor kann mithilfe des Operators >oder >>(Anhängen) zu einem anderen Dateideskriptor oder einer anderen Datei umgeleitet werden .

Verbrauch: < file_descriptor > > < Dateiname | & file_descriptor >

Bitte verweisen Sie auf http://www.tldp.org/LDP/abs/html/io-redirection.html

Quintus.Zhou
quelle
Ihr Beispiel führt etwas anderes aus als das angeforderte OP: Es leitet den stderr von You_commandan stdout und den stdout von You_commandan die Datei um output.log. Außerdem wird es nicht an die Datei angehängt, sondern überschrieben.
Pabouk
Richtig: Der Dateideskriptor kann ein beliebiger Wert sein, der für alle anderen Dateien mehr als 3 beträgt.
Itachi
5
Ihre Antwort zeigt den häufigsten Fehler bei der Ausgabeumleitung: Umleiten von STDERR an die Stelle, auf die STDOUT gerade zeigt, und erst danach Umleiten von STDOUT in eine Datei. Dies führt nicht dazu, dass STDERR in dieselbe Datei umgeleitet wird. Die Reihenfolge der Weiterleitungen ist wichtig.
Jan Wikholm
1
Bedeutet das, ich sollte zuerst STDERROR zu STDOUT umleiten und dann STDOUT zu einer Datei umleiten. 1 > output.log 2>&1
Quintus.Zhou
1
@ Quintus.Zhou Yup. Ihre Version leitet err to out und gleichzeitig out to file weiter.
Alex Yaroshevich
11

Ich bin überrascht, dass in fast zehn Jahren noch niemand diesen Ansatz veröffentlicht hat:

Wenn Sie ältere Versionen von bash verwenden, die &>>nicht verfügbar sind, können Sie auch Folgendes tun:

(cmd 2>&1) >> file.txt

Dieser laicht eine Subshell, so ist es weniger effizient als der traditionelle Ansatz cmd >> file.txt 2>&1, und es wird folglich keine Arbeit für Befehle, die Notwendigkeit , die aktuelle Shell (zB zu modifizieren cd, pushd), aber dieser Ansatz fühlt sich natürlich und verständlich zu mir:

  1. Leiten Sie stderr zu stdout um.
  2. Leiten Sie das neue Standard heraus, indem Sie es an eine Datei anhängen.

Außerdem entfernen die Klammern alle Unklarheiten in der Reihenfolge, insbesondere wenn Sie stattdessen stdout und stderr an einen anderen Befehl weiterleiten möchten.

Jamesdlin
quelle
Diese Implementierung bewirkt, dass ein zusätzlicher Prozess für das System ausgeführt wird. Die Verwendung der Syntax cmd >> file 2>&1funktioniert in allen Shells und erfordert keinen zusätzlichen Prozess zum Ausführen.
Mikko Rantalainen
@MikkoRantalainen Ich habe bereits erklärt, dass es eine Unterschale erzeugt und weniger effizient ist. Der Punkt dieses Ansatzes ist, dass, wenn Effizienz keine große Sache ist (und es selten ist), dieser Weg leichter zu merken und schwerer falsch zu verstehen ist.
Jamesdlin