Ich habe ein Skript, das misst, wie lange ein Befehl ausgeführt wird.
Es benötigt den time
Befehl "real" , was bedeutet, dass beispielsweise eine Binärdatei enthalten ist /usr/bin/time
(da die eingebaute Bash nicht über das -f
Flag verfügt).
Unten ein vereinfachtes Skript, das debuggt werden kann:
#!/bin/bash
TIMESEC=$(echo blah | ( /usr/bin/time -f %e grep blah >/dev/null ) 2>&1 | awk -F. '{print $1}')
echo ABC--$TIMESEC--DEF
if [ "$TIMESEC" -eq 0 ] ; then
echo "we are here!"
fi
Speichern Sie als "test.sh" und führen Sie Folgendes aus:
$ bash test.sh
ABC--0--DEF
we are here!
Also hat es geklappt.
Versuchen wir nun, dies zu debuggen, indem wir "-x" in die Bash-Befehlszeile einfügen:
$ bash -x test.sh
++ echo blah
++ awk -F. '{print $1}'
+ TIMESEC='++ /usr/bin/time -f %e grep blah
0'
+ echo ABC--++ /usr/bin/time -f %e grep blah 0--DEF
ABC--++ /usr/bin/time -f %e grep blah 0--DEF
+ '[' '++ /usr/bin/time -f %e grep blah
0' -eq 0 ']'
test.sh: line 10: [: ++ /usr/bin/time -f %e grep blah
0: integer expression expected
Warum bricht dieses Skript ab, wenn wir "-x" verwenden und es ohne funktioniert?
bash
shell-script
Tomasz Chmielewski
quelle
quelle
-x
on das$()
Konstrukt die-x
Ausgabe als Teil seines resultierenden Wertes erhalten. Ich weiß nicht, ob das ein "erwartetes" Verhalten oder ein Fehler ist ... Oder vielleicht ist es die Subshell()
, die tatsächlich die-x
Ausgabe liefert .BASH_XTRACEFD
können Sie dieset -x
Ausgabe an einen Ort umleiten, an dem es weniger Probleme gibt.Antworten:
Das Problem ist diese Zeile:
Hier leiten Sie den Standardfehler um, damit er mit der Standardausgabe übereinstimmt. Bash schreibt seine Trace-Meldungen in den Standardfehler und verwendet (zum Beispiel) seine eingebauten
echo
zusammen mit anderen Shell-Konstrukten alle im Bash-Prozess.Wenn du es in so etwas wie änderst
Es wird dieses Problem umgehen und möglicherweise ein akzeptabler Kompromiss zwischen Nachverfolgung und Arbeit sein:
quelle
Sie können auch einfach die Unterschale fallen lassen. Anscheinend sind es die verschachtelten Muscheln, die sich gegenseitig stören:
Wenn Sie tun:
... wickeln Sie mit dem Sub - Shell auf dem Markt gebracht, Abschnitt der Pipeline zu behandeln Hosting das Subshell innerhalb. Da die Shell ohne Weiterleitung sogar die Debug-Ausgabe der Subshell in den Abschnitt der Pipeline, in dem Sie Streams mischen, umleitet (wie dies auch für alle anderen Arten von
{
zusammengesetzten; } >redirect
Befehlen der Fall wäre ) . Es hat mit der Reihenfolge der Umleitung zu tun.Wenn Sie stattdessen einfach zuerst nur die Fehlerausgabe der Befehle umleiten , die Sie testen möchten, und die Ausgabe der Host-Shell auf stderr setzen, tritt nicht dasselbe Problem auf.
und so...
... kann die Host-Shell ihren stderr beliebig weiterschreiben und dabei nur die Ausgabe der von ihr aufgerufenen Befehle in die Pipe umleiten.
Übrigens ...
quelle