Wie kann ich BASH-Magie verwenden, um dies zu erreichen?
Ich möchte nur die Ausgabe von stderr auf dem Bildschirm sehen,
aber ich möchte, dass sowohl stdout als auch stderr in eine Datei geschrieben werden.
Klarstellung: Ich möchte, dass sowohl stdout als auch stderr in derselben Datei landen. In der Reihenfolge passieren sie.
Leider tut dies keine der folgenden Antworten.
bash
shell
io-redirection
Andreas
quelle
quelle
Antworten:
Auch ohne Umleitung oder mit nichts anderem
>logfile 2>&1
kann nicht garantiert werden, dass die Ausgabe in der Reihenfolge der Generierung angezeigt wird.Für den Anfang wird die Standardausgabe aus der Anwendung zeilenweise gepuffert (bis tty) oder gepuffert (bis zu einer Pipeline), aber stderr ist ungepuffert, sodass die Beziehungen zwischen der Reihenfolge der Ausgabe für einen Leser unterbrochen werden. Nachfolgende Phasen in einer Pipeline, die Sie erstellen könnten, erhalten keinen deterministisch geordneten Zugriff auf die beiden Streams (dies sind konzeptionell parallele Vorgänge, und Sie sind immer dem Scheduler unterworfen) geschrieben in beide Pipes, man kann nicht sagen, was zuerst kam).
"Die Reihenfolge, in der sie eintreten" ist nur der Anwendung wirklich bekannt. Die Reihenfolge der Ausgabe über stdout / stderr ist ein bekanntes - vielleicht klassisches - Problem.
quelle
Wenn Sie die Konstruktion verwenden:
1>stdout.log 2>&1
Sowohl stderr als auch stdout werden in die Datei umgeleitet, da die stdout- Umleitung vor der stderr- Umleitung eingerichtet wird.Wenn Sie die Reihenfolge umkehren, können Sie stdout in eine Datei umleiten und dann stderr in stdout kopieren , damit Sie es weiterleiten können
tee
.quelle
tee -a
dieselbe Datei verwenden, die in verwendet wird,1>
um beide Ausgaben in derselben Datei zu summieren. So etwas wie:./test 2>&1 1>out+err.log | tee -a out+err.log
wget -O - www.google.de
mir nicht. (vergleiche mit der Lösung unten)tee -a
wird nicht zuverlässig funktionieren, um dieselbe Ausgabe zu erzielen, die sich auf der Konsole befinden würde, wenn nichts umgeleitet würde. Die übermittelte Ausgabe isttee
möglicherweise etwas verzögert im Vergleich zur Ausgabe, die direkt vom Befehl stammt, und wird daher möglicherweise später im Protokoll angezeigt.Ich konnte dies erreichen, indem ich die folgende Zeile oben in ein Bash-Skript einfügte:
Dadurch wird stdout in die Datei
log
(1>>log
) umgeleitet , und stderr wird in die Dateilog
(2> >(tee -a log
) umgeleitet>&2)
. Auf diese Weise erhalte ich eine einzelne Dateilog
, die sowohl stdout als auch stderr in der angegebenen Reihenfolge anzeigt, und stderr auch wie gewohnt auf dem Bildschirm angezeigt.Der Haken ist, dass es nur zu funktionieren scheint, wenn ich an die Datei anhänge. Wenn ich nichts anhänge, scheinen sich die beiden Umleitungen zu überlasten und ich erhalte nur die zuletzt ausgegebenen.
quelle
Sie möchten den Fehlerstrom duplizieren, damit er sowohl in der Konsole als auch in der Protokolldatei angezeigt wird. Das Tool dafür ist
tee
und alles, was Sie tun müssen, ist es auf den Fehlerstrom anzuwenden. Leider gibt es kein Standard-Shell-Konstrukt, um den Fehlerstrom eines Befehls in einen anderen Befehl umzuleiten, sodass eine kleine Neuanordnung der Dateideskriptoren erforderlich ist.quelle
tee
auch hier kommt eine Verzögerung. Ich glaube nicht, dass es eine reine Shell-Lösung gibt. Tatsächlich frage ich mich, ob es eine Lösung gibt, ohne die Anwendung in irgendeiner Weise zu verändern.So schreiben Sie stderr auf den Bildschirm und schreiben BOTH stderr und stdout in eine Datei - UND lassen die Zeilen für stderr und stdout in derselben Reihenfolge erscheinen, in der sie geschrieben würden, wenn beide auf den Bildschirm geschrieben würden:
Es stellt sich als schwieriges Problem heraus, insbesondere der Teil über "dieselbe Sequenz", den Sie erwarten würden, wenn Sie sie einfach auf den Bildschirm schreiben würden. Einfach ausgedrückt: Schreiben Sie jede Zeile in eine eigene Datei, markieren Sie jede Zeile (in jeder Datei) mit der genauen Uhrzeit, zu der die Zeile erstellt wurde, und führen Sie dann Folgendes aus: , aber um BEIDE "stderr" und "stdout" nacheinander zu sehen, sortieren Sie die beiden Dateien (mit exakten Zeitmarkierungen in jeder Zeile) zusammen.
Code:
Ja, dies scheint aufwendig zu sein und führt zu 4 Ausgabedateien (von denen Sie 2 löschen können). Es scheint, dass dies ein schwer zu lösendes Problem ist, daher waren mehrere Mechanismen erforderlich.
Um die Ergebnisse von BOTH stdout und stderr in der erwarteten Reihenfolge zu sehen, führen Sie Folgendes aus:
Der einzige Grund, warum die Sequenz zumindest sehr nahe an dem liegt, was wäre, wenn sowohl stdout als auch stderr einfach auf dem Bildschirm angezeigt worden wären, ist: Jede einzelne Zeile ist bis zur Millisekunde mit einem Zeitstempel versehen.
Gehen Sie wie folgt vor, um stderr im Verlauf des Vorgangs auf dem Bildschirm anzuzeigen:
Hoffe das hilft jemandem, der hier lange angekommen ist, nachdem die ursprüngliche Frage gestellt wurde.
quelle
Geben Sie
f
den Befehl ein, den Sie ausführen möchtensollte dir geben, was du wünschst. Zum Beispiel
wget -O - www.google.de
würde so aussehen:quelle
Angesichts dessen, was ich hier gelesen habe, besteht die einzige Lösung darin, jeder Zeile, ob STOUT oder STERR, eine Zeitscheibe / einen Zeitstempel voranzustellen. Datum +% s würde zu Sekunden werden, aber das ist zu langsam, um die Ordnung aufrechtzuerhalten. Auch das Protokoll müsste irgendwie sortiert werden. Mehr Arbeit als ich kann.
quelle
Ich habe mit genau dieser Anforderung zu kämpfen und konnte am Ende keine einfache Lösung finden. Was ich stattdessen getan habe, war Folgendes:
Es hängt stdout und stderr in der richtigen Reihenfolge an die Protokolldatei an. Und wenn Fehler aufgetreten sind (wie durch den Beendigungsstatus des Befehls bestimmt), sendet er die gesamte Ausgabe (stdout und stderr) wieder in der richtigen verschachtelten Reihenfolge an stdout. Ich fand das ein vernünftiger Kompromiss für meine Bedürfnisse. Wenn Sie eine Protokolldatei mit nur einem Durchlauf anstelle einer wachsenden Protokolldatei mit mehreren Durchläufen möchten, ist dies noch einfacher:
quelle
stderr bis befehlsersetzt
tee -a
und stdout an dieselbe Datei angehängt:und beachte: achte auch auf die richtige Reihenfolge (aber ohne stderr-show), es gibt einen 'Unbuffer'-Befehl von' expect'-Tools, der tty simuliert und stdout / err in der Reihenfolge hält, wie es auf dem Terminal angezeigt würde:
quelle