W wypadku jakichkolwiek skryptów ważne jest pilnowanie poprawności wykonania komend. Każda wykonana komenda zwraca status zakończenia, który jeśli wszystko przebiegło poprawnie powinien być równy zero.
Sprawdźmy to:
# ls
# echo $?
0
Co jednak w wypadku gdy korzystamy z potoku?
Weźmy przykład:
cat plik | gzip > plik2.gz
Co sie stanie jeśli plik nie istnieje? Wykonajmy to polecenie:
cat: plik: No such file or directory
# echo $?
0
Status wykonania polecenia poprawny (zero). Dlaczego? Ponieważ zmienna $? przechowuje stan wykonania ostatniego polecenia. W naszym przykładzie błąd wystąpił przy pierwszym poleceniu - wyświetleniu zawartości pliku. Ponieważ plik nie istniał został wyświetlony błąd - jednak operacja była kontynuowana w potoku. Polecenie gzip wykonało się poprawnie - skompresowało zerowej wielkości strumień wejściowy. Zwrócony status jest więc jak najbardziej w tym wypadku właściwy - mimo, że cała operacja w potoku nie wykonała się po naszej myśli.
W takim wypadku z pomocą przychodzi zmienna $PIPESTATUS - tabela statusów zakończenia poleceń w potoku. Każda kolejna komórka tabeli zawiera status wykonania poszczególnych poleceń. Zobaczmy jak to działa:
cat plik |gzip > plik2.gz
cat: plik: No such file or directory
# echo ${PIPESTATUS[*]}
1 0
Mamy niepoprawny status wykonania cat - jest więc możliwość stwierdzenia błędu wykonania któregoś z poleceń w potoku.
Możemy odwoływać się do poszczególnych komórek tabeli za pomocą indeksu, np. dla pierwszego polecenia będzie to ${PIPESTATUS[0]}. Należy jednak pamiętać o tym, że zawartość zmiennej PIPESTATUS jest 'ulotna', tzn. dostępna jest tylko bezpośrednio po wykonaniu polecenia. Dla zrozumienia pokażę to na poniższym przykładzie:
cat plik |gzip > plik2.gz
cat: plik: No such file or directory
# echo ${PIPESTATUS[*]}
1 0
# echo ${PIPESTATUS[*]}
0
Drugie wykonanie zwraca status wykonania polecenia echo.
W wypadku dłuższych skryptów istnieje możliwość przerwania przetwarzania skryptu w wypadku wystąpienia błędu za pomocą komendy set -e. Myślę, że jest to wygodniejsze niż śledzenie statusów po każdym wywołaniu (chociaż jak zawsze to zależy od tego co robimy).
PS. Możemy wykluczyć poszczególne polecenia w skrypcie z "ostrej" obsługi błędów przy włączonym set -e. Robimy to poprzedzając dane polecenie znakiem wykrzyknika '!'. Polecam manual set
Przydatne odnośniki:
http://tldp.org/LDP/abs/html/internalvariables.html
Brak komentarzy:
Prześlij komentarz