Zu Testzwecken möchte ich stdout und stderr separat zur Überprüfung durch nachfolgenden Code speichern. Zum Beispiel sollte ein Testlauf mit fehlerhafter Eingabe zur Ausgabe in stderr führen, aber nichts in stdout, während ein Testlauf mit korrekter Eingabe zur Ausgabe von stdout, aber nichts zu stderr führen sollte. Die Einsparung muss synchron sein, um Rennbedingungen mit den Tests zu vermeiden (also kann ich process substitution nicht verwenden).Speichern Sie stdout, stderr und stdout + stderr synchron
Um den Test nach der Tat debuggen zu können, muss ich auch stdout und stderr in der Reihenfolge sehen, die sie ausgegeben wurden. Also muss ich sie entweder in der gleichen Datei/Variable/was auch immer speichern oder sie gleichzeitig an das Terminal senden, um sie getrennt zu speichern.
Um zu testen, welcher Fehler passiert ist, brauche ich den Exit-Code des Befehls.
Aus Gründen der Effizienz und Genauigkeit kann ich natürlich nicht jeden Test zweimal durchlaufen.
Ist es beispielsweise möglich, stdout zu stdout.log, stderr zu stderr.log, und beide zu output.log im selben Befehl umleiten? Oder einen synchronentee
Befehl separat für stdout und stderr zu verwenden? Oder um eine Kopie von stdout und stderr in separaten Variablen zu speichern?
aktualisieren: Es sieht aus wie Lösung Tim arbeitet fast (am Terminal zur Ausgabe geändert statt Protokollierung all.log):
mit Ausnahme der letzten Iteration zu arbeiten Dies scheint$ set -o pipefail
$ {
{
echo foo | tee stdout.log 2>&3 3>&-
} 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1
foo
$ cat stdout.log
foo
$ cat stderr.log
$ {
{
echo foo >&2 | tee stdout.log 2>&3 3>&-
} 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1
foo
$ cat stdout.log
$ cat stderr.log
foo
$ bar=$({
{
echo foo | tee stdout.log 2>&3 3>&-
} 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1)
$ echo "$bar"
foo
$ cat stdout.log
foo
$ cat stderr.log
$ bar=$({
{
echo foo >&2 | tee stdout.log 2>&3 3>&-
} 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1)
$ cat stdout.log
$ cat stderr.log
foo
$ echo "$bar"
foo
, wobei der Wert von bar
wird auf den Inhalt von stderr festgelegt. Irgendwelche Vorschläge für alle diese zu arbeiten?
wir reden zeilenbasierte Strings Angenommen, wir können beide Rohrströme durch, sagen wir, 'sed' Markierungen am Zeilenanfang hinzufügen? Dann könnten wir anhand der Protokolldatei feststellen, welche Zeile aus welchem Stream stammt. – Raphael
@Raphael: Sie sollten in der Lage sein, 'Tee' innerhalb jeder Prozesssubstitution vorauszusetzen, zum Beispiel:' exec>> (sed 's/^/von STDOUT: /' | tee -a mylog) 2>> (sed 's/^/von STDERR:/'| tee -a mylog> & 2) '(ungetestet). Dies würde übrigens dazu führen, dass die Ausgabe an das Terminal auch diese Präfixe aufweist. –
Cool! Verletzt das nicht einen Teil des Zitats, das Sie geben? Jetzt haben wir eine synchronisierte gemeinsame Ausgabedatei und wissen immer noch welche welche war, oder fehlt mir etwas? – Raphael