Mam skrypt mierzący czas wykonywania niektórych poleceń.
Potrzebuje polecenia „rzeczywistego” time
, czyli binarnego na przykład w /usr/bin/time
(ponieważ wbudowany bash nie ma -f
flagi).
Poniżej uproszczony skrypt, który można debugować:
#!/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
Zapisz jako „test.sh” i wykonaj:
$ bash test.sh
ABC--0--DEF
we are here!
Więc zadziałało.
Teraz spróbujmy to debugować, dodając „-x” do wiersza poleceń bash:
$ 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
Dlaczego ten skrypt się psuje, gdy używamy „-x” i działa bez niego dobrze?
bash
shell-script
Tomasz Chmielewski
źródło
źródło
-x
na to, że z$()
konstrukcją-x
włącza się wynik jako część jego wynikowej wartości. Nie wiem jednak, czy jest to „oczekiwane” zachowanie, czy błąd… A może to właśnie()
wewnętrzna powłoka daje-x
wynik.BASH_XTRACEFD
pozwala przekierowaćset -x
wyjście do miejsca, w którym jest mniej problemów.Odpowiedzi:
Problemem jest ta linia:
gdzie przekierowujesz standardowy błąd, aby dopasować go do standardowego wyjścia. bash zapisuje swoje komunikaty śledzenia do standardowego błędu i używa (na przykład) swojej wbudowanej aplikacji
echo
wraz z innymi konstrukcjami powłoki w procesie bash.Jeśli zmienisz to na coś takiego
obejdzie ten problem i być może będzie akceptowalnym kompromisem między śledzeniem a działaniem:
źródło
możesz także po prostu upuścić podpowłokę. najwyraźniej są to zagnieżdżone muszle, które wzajemnie się denerwują:
Jeśli zrobisz:
... kończysz z uruchomioną podpowłoką, aby obsłużyć tę sekcję potoku, w której znajduje się podpowłoka. Ponieważ powłoka bez przekierowuje nawet dane wyjściowe debugowania podpowłoki wewnątrz (tak jak w przypadku każdego innego
{
polecenia złożonego,; } >redirect
którego możesz użyć) do swojej części potoku, kończysz mieszanie strumieni. Ma to związek z kolejnością przekierowań.Zamiast tego, jeśli po prostu najpierw przekierujesz tylko wyjście błędu poleceń, które próbujesz zmierzyć, i pozwolisz, aby wyjście powłoki hosta osiągnęło stderr, nie skończysz z tym samym problemem.
a więc...
... powłoka hosta może kontynuować zapisywanie swojego stderr tam, gdzie chce, a jedynie przekierowywać wyjście poleceń, które wywołuje do potoku.
Z tego powodu...
źródło