Czy istnieje sposób na debugowanie skryptu bash? Np. Coś, co drukuje rodzaj dziennika wykonywania, jak „linia wywołująca 1”, „linia wywołująca 2” itd.
Czy istnieje sposób na debugowanie skryptu bash? Np. Coś, co drukuje rodzaj dziennika wykonywania, jak „linia wywołująca 1”, „linia wywołująca 2” itd.
Odpowiedzi:
sh -x script [arg1 ...]
bash -x script [arg1 ...]
Dają ci ślad tego, co jest wykonywane. (Zobacz także „Wyjaśnienie” u dołu odpowiedzi).
Czasami trzeba kontrolować debugowanie w skrypcie. W takim razie, jak przypomniał mi Cheeto , możesz użyć:
set -x
To włącza debugowanie. Następnie możesz go ponownie wyłączyć za pomocą:
set +x
(Możesz sprawdzić bieżący stan śledzenia, analizując $-
bieżące flagi dla x
).
Ponadto powłoki generalnie udostępniają opcje „ -n
” dla „braku wykonywania” i „ -v
” dla trybu „gadatliwego”; możesz użyć ich w połączeniu, aby sprawdzić, czy powłoka uważa, że może wykonać twój skrypt - czasami przydatne, jeśli gdzieś masz niezrównoważony cytat.
Istnieje twierdzenie, że -x
opcja „ ” w Bash różni się od innych powłok (patrz komentarze). Instrukcja Bash mówi:
-x
Wydrukuj ślad prostych poleceń, for
poleceń, case
poleceń, select
poleceń i for
poleceń arytmetycznych oraz ich argumentów lub powiązanych list słów po ich rozwinięciu i przed wykonaniem. Wartość PS4
zmiennej jest interpretowana, a wynikowa wartość jest wypisywana przed poleceniem i jego rozwiniętymi argumentami.
To wcale nie wydaje się wskazywać na inne zachowanie. Nie widzę żadnych innych odnośnych odniesień do „ -x
” w instrukcji. Nie opisuje różnic w kolejności startowej.
Wyjaśnienie : W systemach takich jak typowy Linux, gdzie „ /bin/sh
” jest dowiązaniem symbolicznym do „ /bin/bash
” (lub gdziekolwiek zostanie znaleziony plik wykonywalny Bash), dwie linie poleceń osiągają równoważny efekt uruchamiania skryptu z włączonym śledzeniem wykonania. W innych systemach (na przykład Solaris i niektóre bardziej nowoczesne warianty Linuksa) /bin/sh
nie jest Bash, a dwie linie poleceń dałyby (nieco) różne wyniki. Przede wszystkim „ /bin/sh
” byłby zdezorientowany przez konstrukcje w Bash, których w ogóle nie rozpoznaje. (W Solarisie /bin/sh
jest to powłoka Bourne'a; we współczesnym Linuksie jest to czasami Dash - mniejsza, bardziej ściśle zgodna tylko z POSIX-owa powłoka). Po wywołaniu z taką nazwą, linia „shebang” ( #!/bin/bash
„vs '#!/bin/sh
”
Podręcznik Bash zawiera sekcję o trybie Bash POSIX, który w przeciwieństwie do długotrwałej, ale błędnej wersji tej odpowiedzi (zobacz również komentarze poniżej), opisuje szczegółowo różnicę między 'Bash wywołany jako sh
' a 'Bash wywołany jako' bash
”.
Podczas debugowania (Bash) skryptu powłoki rozsądne i rozsądne będzie - nawet konieczne - użycie powłoki wymienionej w linii shebang z -x
opcją. W przeciwnym razie możesz (będzie?) Uzyskać inne zachowanie podczas debugowania niż podczas uruchamiania skryptu.
bash
scenariusz. Uruchomienie skryptu bash w programie sh -x
sprawi, że będzie się on zachowywał zupełnie inaczej! Zaktualizuj swoją odpowiedź.
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
Użyłem następujących metod do debugowania mojego skryptu.
set -e
powoduje natychmiastowe zatrzymanie skryptu, jeśli jakikolwiek program zewnętrzny zwróci niezerowy kod zakończenia. Jest to przydatne, jeśli twój skrypt próbuje obsłużyć wszystkie przypadki błędów i gdzie niepowodzenie powinno zostać złapane.
set -x
został wspomniany powyżej iz pewnością jest najbardziej użyteczną ze wszystkich metod debugowania.
set -n
może być również przydatne, jeśli chcesz sprawdzić skrypt pod kątem błędów składniowych.
strace
jest również przydatne, aby zobaczyć, co się dzieje. Szczególnie przydatne, jeśli sam nie napisałeś scenariusza.
strace -f
jest to potrzebne, jeśli chcesz również znaleźć błędy w procesach uruchomionych przez skrypt. (co sprawia, że jest wielokrotnie bardziej rozwlekły, ale nadal przydatny, jeśli ograniczysz go do wywołań systemowych, które Cię interesują).
set -e
jest ... kontrowersyjny .
Ta odpowiedź jest poprawna i przydatna: https://stackoverflow.com/a/951352
Jednak uważam, że „standardowe” metody debugowania skryptów są nieefektywne, nieintuicyjne i trudne w użyciu. Dla osób przyzwyczajonych do wyrafinowanych debuggerów GUI, które umieszczają wszystko na wyciągnięcie ręki i sprawiają, że praca jest szybka w przypadku łatwych problemów (i możliwych w przypadku trudnych problemów), te rozwiązania nie są zbyt satysfakcjonujące.
Używam kombinacji DDD i bashdb. Pierwsza wykonuje drugą, a druga wykonuje skrypt. Zapewnia to interfejs użytkownika z wieloma oknami z możliwością przechodzenia przez kod w kontekście i przeglądania zmiennych, stosu itp., Bez ciągłego wysiłku umysłowego w celu utrzymania kontekstu w głowie lub ponownego wyświetlania źródła.
Wskazówki, jak to zrobić, znajdziesz tutaj: http://ubuntuforums.org/showthread.php?t=660223
W skrypcie można również napisać „set -x”.
Znalazłem narzędzie Shellcheck i może być dla niektórych osób interesujące https://github.com/koalaman/shellcheck
Mały przykład:
$ cat test.sh
ARRAY=("hello there" world)
for x in $ARRAY; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in $ARRAY; do
^-- SC2128: Expanding an array without an index only gives the first element.
napraw błąd, najpierw spróbuj ...
$ cat test.sh
ARRAY=("hello there" world)
for x in ${ARRAY[@]}; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in ${ARRAY[@]}; do
^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
Spróbujmy ponownie...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
Znajdź teraz!
To tylko mały przykład.
Użyj zaćmienia z powłoką wtyczek i basheclipse.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Dla powłoki: pobierz plik zip i zaimportuj go do eclipse za pomocą pomocy -> zainstaluj nowe oprogramowanie: archiwum lokalne Dla basheclipse: skopiuj jars do katalogu dropins w eclipse
Postępuj zgodnie z instrukcjami https://sourceforge.net/projects/basheclipse/files/?source=navbar
Napisałem samouczek z wieloma zrzutami ekranu na http://dietrichschroff.blogspot.de/2017/07/bash-eniring-eclipse-for-bash.html
Zbudowałem debugger Bash. Po prostu daj temu szansę. Mam nadzieję, że pomoże https://sourceforge.net/projects/bashdebugingbash
set + x = @ECHO OFF, set -x = @ECHO ON.
Możesz dodać -xv
opcję do standardowego Shebanga w następujący sposób:
#!/bin/bash -xv
-x
: Wyświetla polecenia i ich argumenty w trakcie ich wykonywania.
-v
: Wyświetla linie wejściowe powłoki w trakcie ich czytania.
ltrace
jest kolejnym narzędziem Linux podobnym do strace
. Jednak ltrace
zawiera listę wszystkich wywołań biblioteki wywoływanych w pliku wykonywalnym lub działającym procesie. Sama nazwa pochodzi od śledzenia wywołań bibliotecznych. Na przykład:
ltrace ./executable <parameters>
ltrace -p <PID>
Myślę, że możesz wypróbować ten debugger Bash: http://bashdb.sourceforge.net/ .
set -[nvx]
Oprócz
set -x
i
set +x
za zatrzymanie zrzutu.
Chciałbym mówić o tym, set -v
który zrzut jest mniejszy niż mniej rozwinięta produkcja.
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21
for arg in x v n nx nv nvx;do echo "- opts: $arg"
bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
set -$arg
for i in {0..9};do
echo $i
done
set +$arg
echo Done.
eof
sleep .02
done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5
Do testowania niektórych zmiennych używam czasami tego:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
za dodanie:
declare >&2 -p var1 var2
w linii 18. i uruchamiając wynikowy skrypt (z argumentami ), bez konieczności ich edycji.
oczywiście można to wykorzystać do dodania set [+-][nvx]
:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
doda declare -p v1 v2 >&2
po linii 18, set -x
przed linią 22 i set +x
przed linią 26.
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8
Uwaga: Pielęgnacja o $LINENO
wpłynie on-the-fly modyfikacje!
(Aby zobaczyć wynikowy skrypt bez wykonywania, po prostu upuść bash <(
i ) arg1 arg2
)
Spójrz na moją odpowiedź dotyczącą profilowania skryptów bash
Jest dużo szczegółów dotyczących rejestrowania skryptów powłoki za pośrednictwem globalnych zmiennych powłoki. Możemy emulować podobny rodzaj logowania w skrypcie powłoki: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
W poście znajdują się szczegółowe informacje o wprowadzaniu poziomów dziennika, takich jak INFO, DEBUG, ERROR. Śledzenie szczegółów, takich jak wpis skryptu, wyjście skryptu, wejście funkcji, wyjście funkcji.
Przykładowy dziennik: