Zrobiłem następujący skrypt:
# !/bin/bash
# OUTPUT-COLORING
red='\e[0;31m'
green='\e[0;32m'
NC='\e[0m' # No Color
# FUNCTIONS
# directoryExists - Does the directory exist?
function directoryExists {
cd $1
if [ $? = 0 ]
then
echo -e "${green}$1${NC}"
else
echo -e "${red}$1${NC}"
fi
}
# EXE
directoryExists "~/foobar"
directoryExists "/www/html/drupal"
Skrypt działa, ale poza moimi echami jest też wyjście kiedy
cd $1
kończy się niepowodzeniem podczas wykonywania.
testscripts//test_labo3: line 11: cd: ~/foobar: No such file or directory
Czy można to złapać?
bash
shell
shell-script
error-handling
Thomas De Wilde
źródło
źródło
test -d /path/to/directory
(lub[[ -d /path/to/directory ]]
w bash) powie ci, czy dany cel jest katalogiem, czy nie, i zrobi to po cichu.cd
do niego wejść.directoryExists
.Odpowiedzi:
Twój skrypt zmienia katalogi podczas działania, co oznacza, że nie będzie działał z serią względnych ścieżek. Później skomentowałeś, że chcesz tylko sprawdzić istnienie katalogu, a nie możliwość korzystania z niego
cd
, więc odpowiedzi wcale nie muszą być używanecd
. Ulepszony. Używanietput
i kolory zman terminfo
:(Edytowane, aby użyć bardziej niewrażliwego
printf
zamiast problematycznego,echo
który może działać na sekwencje specjalne w tekście).źródło
Służy
set -e
do ustawiania trybu wyjścia po błędzie: jeśli proste polecenie zwraca stan niezerowy (wskazujący błąd), powłoka wychodzi.Pamiętaj, że
set -e
nie zawsze kopać. Polecenia na stanowiskach testowych mogą zawieść (npif failing_command
,failing_command || fallback
). Polecenia w podpowłoce prowadzą tylko do wyjścia z podpowłoki, a nie nadrzędnego:set -e; (false); echo foo
wyświetlafoo
.Alternatywnie lub dodatkowo w bash (i ksh i zsh, ale nie zwykłym sh), możesz określić polecenie, które zostanie wykonane w przypadku, gdy polecenie zwróci niezerowy status, z
ERR
pułapką, nptrap 'err=$?; echo >&2 "Exiting on error $err"; exit $err' ERR
. Zauważ, że w takich przypadkach(false); …
pułapka ERR jest wykonywana w podpowłoce, więc nie może spowodować wyjścia rodzica.źródło
||
zachowania, który umożliwia łatwe wykonywanie prawidłowej obsługi błędów bez użycia pułapek. Zobacz moją odpowiedź . Co sądzisz o tej metodzie?ERR
pseudo-sygnał jest obsługiwany we wszystkich głównych powłokach. Dzięki za recenzję! =)Aby rozwinąć odpowiedź @Gilles :
Rzeczywiście,
set -e
nie działa wewnątrz poleceń, jeśli używasz||
operatora po nich, nawet jeśli uruchamiasz je w podpowłoce; np. to nie zadziała:Ale
||
operator jest potrzebny, aby zapobiec powrotowi z funkcji zewnętrznej przed czyszczeniem.Jest mała sztuczka, której można użyć, aby to naprawić: uruchom wewnętrzne polecenie w tle, a następnie natychmiast poczekaj na to.
wait
Wbudowane zwróci kod wyjścia polecenia wewnętrznej, a teraz używasz||
powait
, a nie funkcji wewnętrznej, więcset -e
działa prawidłowo wewnątrz tego ostatniego:Oto ogólna funkcja oparta na tej idei. Powinien on działać we wszystkich powłokach zgodnych z POSIX, jeśli usuniesz
local
słowa kluczowe, tzn. Zastąpiszlocal x=y
je tylkox=y
:Przykład użycia:
Uruchamianie przykładu:
Jedyną rzeczą, o której musisz wiedzieć, używając tej metody, jest to, że wszystkie modyfikacje zmiennych Shell wykonane z komendy, którą przekazujesz
run
, nie będą propagowane do funkcji wywołującej, ponieważ komenda działa w podpowłoce.źródło
Nie mówisz, co dokładnie rozumiesz przez
catch
--- zgłoś i kontynuuj; przerwać dalsze przetwarzanie?Ponieważ
cd
w przypadku niepowodzenia zwraca stan niezerowy, możesz:Możesz po prostu wyjść w przypadku awarii:
Lub wyświetl własną wiadomość i wyjdź:
I / lub ukryć błąd dostarczony przez
cd
w przypadku awarii:Zgodnie ze standardami polecenia powinny umieszczać komunikaty o błędach w STDERR (deskryptor pliku 2). Tak
2>/dev/null
mówi przekierowanie STDERR do „wiadra bitów” znanego przez/dev/null
.(nie zapomnij podać swoich zmiennych i zaznaczyć koniec opcji dla
cd
).źródło
Właściwie w twoim przypadku powiedziałbym, że logikę można poprawić.
Zamiast cd, a następnie sprawdź, czy istnieje, sprawdź, czy istnieje, a następnie przejdź do katalogu.
Ale jeśli Twoim celem jest uciszenie możliwych błędów
cd -- "$1" 2>/dev/null
, to jednak utrudni to debugowanie w przyszłości. Możesz sprawdzić, czy flagi testowe znajdują się w: Bash, jeśli dokumentacja :źródło
$1
zmiennej i nie powiedzie się, jeśli zmienna zawiera spacje lub inne metaznaki powłoki. Nie sprawdza również, czy użytkownik macd
na to pozwolenie .