Próbuję utworzyć raportowanie błędów za pomocą pułapki w celu wywołania funkcji dla wszystkich błędów:
Trap "_func" ERR
Czy można uzyskać informację, z której linii wysłano sygnał ERR? Powłoka to bash.
Jeśli to zrobię, mogę odczytać i zgłosić, które polecenie zostało użyte, i zarejestrować / wykonać niektóre działania.
A może źle to rozumiem?
Testowałem z następującymi:
#!/bin/bash
trap "ECHO $LINENO" ERR
echo hello | grep "asdf"
I $LINENO
wraca 2. Nie działa.
bash
shell-script
error-handling
trap
Mechaflash
źródło
źródło
bashdb
. Wydaje się, że pierwszy argumenttrap
może zawierać zmienne, które są oceniane w pożądanym kontekście. Taktrap 'echo $LINENO' ERR'
powinno działać.trap 'echo $LINENO' ERR
. Pierwszym argumentemtrap
jest całyecho $LINENO
zacytowany. To jest bash.trap 'echo $LINENO' ERR
, z pojedynczymi cudzysłowami, a nie podwójnymi cudzysłowami. Polecenie, które napisałeś,$LINENO
jest rozszerzane, gdy linia 2 jest analizowana, więc pułapka jestecho 2
(a raczejECHO 2
, która by wyprowadziłabash: ECHO: command not found
).Odpowiedzi:
Jak wskazano w komentarzach, twoje cytaty są błędne. Potrzebujesz pojedynczych cudzysłowów, aby zapobiec
$LINENO
rozszerzaniu przy pierwszej analizie linii pułapki.To działa:
Uruchamianie:
źródło
echo hello | grep foo
nie wydaje mi się, że to błąd. Czy coś nie rozumiem?grep
ma status wyjścia 0, jeśli było dopasowanie, 1, jeśli nie było dopasowania i> 1 dla błędu. Możesz sprawdzić zachowanie w swoim systemie za pomocąecho hello | grep foo; echo $?
Możesz także użyć wbudowanego programu wywołującego bash:
wypisuje także nazwę pliku:
źródło
Naprawdę podoba mi się odpowiedź udzielona przez @Mat powyżej. Opierając się na tym, napisałem małego pomocnika, który daje nieco więcej kontekstu dla błędu:
Możemy sprawdzić skrypt pod kątem linii, która spowodowała błąd:
Oto w małym skrypcie testowym:
Po uruchomieniu otrzymujemy:
źródło
$(caller)
danych do podania kontekstu, nawet jeśli błąd nie jest w bieżącym skrypcie, ale jednym z jego importów. Ale bardzo miło!Zainspirowany inną odpowiedzią, oto prostsza kontekstowa procedura obsługi błędów:
W razie potrzeby możesz także użyć awk zamiast ogona i głowy .
źródło
Oto kolejna wersja, zainspirowana @sanmai i @unpythonic. Pokazuje wiersze skryptu wokół błędu, z numerami linii i statusem wyjścia - używając tail & head, ponieważ wydaje się to prostsze niż rozwiązanie awk.
Pokazuje to jako dwa wiersze dla czytelności - możesz połączyć te wiersze w jeden, jeśli wolisz (zachowując
;
):Działa to całkiem dobrze z
set -euo pipefail
( nieoficjalnym trybem ścisłym ) - każdy niezdefiniowany błąd zmiennej podaje numer linii bez odpaleniaERR
pseudo-sygnału, ale inne przypadki pokazują kontekst.Przykładowe dane wyjściowe:
źródło
Tak,
LINENO
aBASH_LINENO
zmienne są kolacją przydatną do uzyskania linii awarii i linii, które do niej prowadzą.Nie, po prostu brakuje
-q
opcji z grep ...... Z
-q
opcjągrep
wróci0
zatrue
i1
zafalse
. A w Bash totrap
nie jestTrap
...Oto traper, który może się przydać do debugowania rzeczy o bardziej złożonej cykliczności ...
failure.sh
... i przykładowy skrypt użycia do ujawnienia subtelnych różnic w ustawianiu powyższej pułapki do śledzenia funkcji również ...
example_usage.sh
Powyższe testy zostały przetestowane na Bash w wersji 4+, więc zostaw komentarz, jeśli coś jest potrzebne w wersjach wcześniejszych niż cztery, lub otwórz problem, jeśli nie uda mu się uchwycić błędów w systemach z wersją minimum czterech.
Główne dania na wynos to ...
-E
powoduje powiększanie się błędów w funkcjach-o functrace
powoduje pozwala na większą gadatliwość, gdy coś w funkcji zawiedziePojedyncze cudzysłowy są używane wokół wywołania funkcji, a podwójne cudzysłowy wokół poszczególnych argumentów
Odwołania do
LINENO
iBASH_LINENO
są przekazywane zamiast bieżących wartości, chociaż może to zostać skrócone w późniejszych wersjach programu powiązanego z pułapką, tak że końcowa linia awarii powoduje jej wyjścieWartości
BASH_COMMAND
i status exit ($?
) są przekazywane, po pierwsze, aby uzyskać polecenie, które zwróciło błąd, a po drugie, aby upewnić się, że pułapka nie wyzwala się w stanach innych niż błądPodczas gdy inni mogą się nie zgodzić, uważam, że łatwiej jest zbudować tablicę wyjściową i użyć printf do wydrukowania każdego elementu tablicy we własnej linii ...
... także
>&2
bit na końcu powoduje, że błędy idą tam, gdzie powinny (błąd standardowy), i pozwala uchwycić tylko błędy ...Jak pokazują te i inne przykłady dotyczące przepełnienia stosu, istnieje wiele sposobów na zbudowanie pomocy do debugowania przy użyciu wbudowanych narzędzi.
źródło