web-dev-qa-db-de.com

So leiten Sie die Ausgabe in eine Datei und in eine Standardausgabe um

In bash würde der Aufruf von foo alle Ausgaben dieses Befehls auf dem Standardausgang anzeigen.

Wenn Sie foo > output aufrufen, werden alle Ausgaben dieses Befehls in die angegebene Datei umgeleitet (in diesem Fall 'Ausgabe').

Gibt es eine Möglichkeit, die Ausgabe in eine Datei und umzuleiten, die auf stdout angezeigt wird?

754
SCdF

Der gewünschte Befehl heißt tee:

foo | tee output.file

Wenn Sie sich beispielsweise nur für stdout interessieren:

ls -a | tee output.file

Wenn Sie stderr einschließen möchten, machen Sie Folgendes:

program [arguments...] 2>&1 | tee outfile

2>&1 leitet Kanal 2 (stderr/standard error) in Kanal 1 (stdout/standard output) um, so dass beide als stdout geschrieben werden. Es ist auch auf die angegebene Ausgabedatei ab dem Befehl tee gerichtet.

Wenn Sie anhängen an die Protokolldatei anhängen möchten, verwenden Sie tee -a wie folgt:

program [arguments...] 2>&1 | tee -a outfile
1031
Zoredache
$ program [arguments...] 2>&1 | tee outfile

2>&1 gibt die Streams stderr und stdout aus .__tee outfile nimmt den erhaltenen Stream und schreibt ihn auf den Bildschirm und in die Datei "outfile".

Dies ist wahrscheinlich das, was die meisten Leute suchen. Die wahrscheinliche Situation ist, dass ein Programm oder Skript lange Zeit hart arbeitet und eine Menge Ausgabe erzeugt. Der Benutzer möchte ihn regelmäßig auf Fortschritt überprüfen, die Ausgabe jedoch auch in eine Datei schreiben.

Das Problem (insbesondere beim Mischen von stdout- und stderr-Streams) besteht darin, dass die Streams vom Programm abhängig sind. Wenn zum Beispiel alle Schreibvorgänge an stdout nicht gelöscht werden, aber alle Schreibvorgänge an stderr [ gelöscht werden, werden sie in der Ausgabedatei und auf dem Bildschirm nicht in chronologischer Reihenfolge angezeigt.

Es ist auch schlecht, wenn das Programm alle paar Minuten nur 1 oder 2 Zeilen ausgibt, um den Fortschritt zu melden. Wenn die Ausgabe nicht vom Programm geleert wurde, kann der Benutzer in diesem Fall auch stundenlang keine Ausgabe auf dem Bildschirm sehen, da keine davon stundenlang durch die Pipe geschoben wird.

Update: Das Programm unbuffer, Teil des expect-Pakets, löst das Pufferproblem. Dies führt dazu, dass stdout und stderr sofort auf den Bildschirm und die Datei schreiben und diese synchron halten, wenn sie kombiniert und zu tee umgeleitet werden. Z.B.:

$ unbuffer program [arguments...] 2>&1 | tee outfile
459
Matthew Alpert

Ein anderer Weg, der für mich funktioniert, ist,

<command> |& tee  <outputFile>

wie in gnu bash manual gezeigt

Beispiel:

ls |& tee files.txt

Wenn '| &' verwendet wird, wird der Standardfehler von Befehl1 zusätzlich zu seiner Standardausgabe wird über die Pipe mit dem Standardeingang von command2 verbunden; es ist Kurzform für 2> & 1 |. Diese implizite Umleitung des Standardfehlers auf die Standardausgabe erfolgt nach allen vom Befehl angegebenen Umleitungen.

Weitere Informationen finden Sie unter Weiterleitung .

115
tsenapathy

Sie können hauptsächlich Zoredachesolution verwenden, aber wenn Sie die Ausgabedatei nicht überschreiben möchten, sollten Sie tee mit der Option -a wie folgt schreiben:

ls -lR / | tee -a output.file
16
O.Badr

Etwas hinzuzufügen ...

Das Paket Unpuffer hat Supportprobleme mit einigen Paketen unter Fedora und Redhat Unix-Versionen.

Die Probleme beiseite stellen 

Folgendes arbeitete für mich

bash myscript.sh 2>&1 | tee output.log

Danke ScDF & matthew Ihre Eingaben haben mir viel Zeit gespart.

11
nitinr708

mit tail -f output sollte funktionieren.

6
Chuck Phillips

Die Bonusantwort seit diesem Anwendungsfall hat mich hierher gebracht:

In dem Fall, dass Sie dies als ein anderer Benutzer tun müssen

echo "some output" | Sudo -u some_user tee /some/path/some_file

Beachten Sie, dass das Echo so erfolgt, wie Sie es tun, und das Schreiben der Datei als "some_user" erfolgt. Dies funktioniert NICHT , wenn Sie das Echo als "some_user" ausführen "und leiten Sie die Ausgabe mit >>" some_file "um, da die Dateiumleitung so erfolgt, wie Sie es möchten.

Tipp: tee unterstützt auch das Anhängen mit dem Flag -a, wenn Sie eine Zeile in einer Datei als anderer Benutzer ersetzen müssen, den Sie als gewünschten Benutzer ausführen könnten.

3
jorfus

< command > |& tee filename # erstellt eine Datei "Dateiname" mit Befehlsstatus als Inhalt. Wenn bereits eine Datei vorhanden ist, wird vorhandener Inhalt entfernt und der Befehlsstatus wird geschrieben.

< command > | tee >> filename # Der Status wird an die Datei angehängt, der Befehlsstatus wird jedoch nicht auf standard_output (screen) gedruckt.

Ich möchte etwas drucken, indem Sie "Echo" auf dem Bildschirm verwenden und diese Daten an eine Datei anhängen

echo "hi there, Have to print this on screen and append to a file" 
0
kiran sai

Sie können dies für Ihr gesamtes Skript tun, indem Sie am Anfang Ihres Skripts so etwas verwenden:

#!/usr/bin/env bash

test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "[email protected]" ) | tee mylogfile ; exit $? ; }

# do whaetever you want

Diese Umleitung von stderr- und stdout-Ausgaben in die Datei mylogfileund lässt alles zu stdout zur gleichen Zeit gehen.

Es werden ein paar blöde Tricks angewendet:

  • verwenden Sie exec ohne Befehl, um Umleitungen einzurichten.
  • benutze tee um Ausgaben zu duplizieren,
  • starten Sie das Skript mit den gewünschten Weiterleitungen neu.
  • verwenden Sie einen speziellen ersten Parameter (ein einfaches Zeichen NUL, das in der speziellen Bash-Notation $'string' angegeben ist), um anzugeben, dass das Skript neu gestartet wird (von Ihrer ursprünglichen Arbeit darf kein äquivalenter Parameter verwendet werden).
  • versuchen Sie, den ursprünglichen Beendigungsstatus beizubehalten, wenn Sie das Skript mit der Option pipefail neu starten.

Hässlich aber nützlich für mich in bestimmten Situationen.

0
Bruno BEAUFILS