Jak znaleźć numer linii w Bash, w którym wystąpił błąd?
Przykład
Tworzę następujący prosty skrypt z numerami linii, aby wyjaśnić, czego potrzebujemy. Skrypt skopiuje pliki z
cp $file1 $file2
cp $file3 $file4
Gdy jedno z cp
poleceń nie powiedzie się, funkcja zakończy działanie z wyjściem 1 . Chcemy dodać funkcję do funkcji drukowania błędu również z numerem linii (na przykład 8 lub 12).
czy to możliwe?
Przykładowy skrypt
1 #!/bin/bash
2
3
4 function in_case_fail {
5 [[ $1 -ne 0 ]] && echo "fail on $2" && exit 1
6 }
7
8 cp $file1 $file2
9 in_case_fail $? "cp $file1 $file2"
10
11
12 cp $file3 $file4
13 in_case_fail $? "cp $file3 $file4"
14
set -x
i / lubset -v
do śledzenia tego, co zostało wykonane. Niezupełnie to, o co prosiłeś, ale prawdopodobnie też będzie pomocne.Odpowiedzi:
Zamiast używać twojej funkcji, zamiast tego użyłbym tej metody:
Działa to poprzez pułapkę na ERR, a następnie wywołanie
failure()
funkcji z bieżącym numerem linii + wykonaną komendą bash.Przykład
Tutaj nie podjęliśmy żadnych starań, aby tworzyć pliki,
f1
,f2
,f3
, lubf4
. Po uruchomieniu powyższego skryptu:Nie udaje się, zgłaszając numer wiersza plus wykonane polecenie.
źródło
Oprócz
LINENO
zawierającego bieżący numer linii, są teżBASH_LINENO
iFUNCNAME
(iBASH_SOURCE
tablice ), które zawierają nazwy funkcji i numery linii, z których są wywoływane.Więc możesz zrobić coś takiego:
Uruchomienie, które zostanie wydrukowane
Jeśli używasz
set -e
lubtrap ... ERR
automatycznie wykrywasz błędy, zauważ, że mają one pewne zastrzeżenia. Trudniej jest także dołączyć opis działania skryptu w tym czasie (tak jak w przykładzie), chociaż może to być bardziej użyteczne dla zwykłego użytkownika niż tylko numer wiersza.Zobacz np. Te problemy z
set -e
i innymi:źródło
Bash ma wbudowaną zmienną,
$LINENO
która jest zastępowana bieżącym numerem wiersza w instrukcji, więc możesz to zrobićMożesz także spróbować użyć,
trap ... ERR
który uruchamia się, gdy polecenie nie powiedzie się (jeśli wynik nie zostanie przetestowany). Na przykład:Jeśli takie polecenie
cp $file1 $file2
nie powiedzie się, otrzymasz komunikat o błędzie z numerem wiersza i wyjściem. Polecenie znajdziesz również w błędzie w zmiennej$BASH_COMMAND
(choć nie ma żadnych przekierowań itp.).źródło