Unikaj uruchamiania skryptu, jeśli zmienna nie jest zdefiniowana

18

Mam skrypt wygląda następująco:

c=0
for f in */*; do
cp -v "$f" "/myhome/CE$(printf '%0*d' 2 $BATCHNUM)-new-stuctures_extracted/test-$(printf '%0*d' 5 $c)"
c=$((c=c+1))
done

Jednak użytkownik musi podać zmienne wywołanie BATCHNUM, w przeciwnym razie muszę wymusić zatrzymanie działania tego skryptu. Byłoby lepiej, gdybym mógł zmusić skrypt, który wywołuje ten skrypt, do zatrzymania się (lub nawet skrypt nr 1, który wywołuje skrypt nr 2, który wywołuje ten skrypt).

użytkownik40780
źródło

Odpowiedzi:

30

Najszybszym sposobem jest prawdopodobnie dodanie tych dwóch wierszy na początku skryptu:

set -u # or set -o nounset
: "$BATCHNUM"

Pierwszy wiersz ustawia nounsetopcję w powłoce uruchamiającej skrypt, która przerywa się, jeśli spróbujesz rozwinąć nieokreśloną zmienną; drugi rozszerza się $BATCHNUMw kontekście braku operacji, aby wywołać przerwanie przed zrobieniem czegokolwiek innego.

Jeśli potrzebujesz bardziej pomocnego komunikatu o błędzie, możesz zamiast tego napisać:

if [[ -z "$BATCHNUM" ]]; then
    echo "Must provide BATCHNUM in environment" 1>&2
    exit 1
fi

Lub podobne.

Tom Hunt
źródło
18

Tutaj chcesz sprawdzić, czy BATCHNUMjest ustawiona, a nie zerowa.

Powłoka POSIX zapewnia rozszerzenie parametru dla tego zadania. Po prostu dodaj ten wiersz przed użyciem BATCHNUM:

: "${BATCHNUM:?Variable not set or empty}"

lub lepiej ustawić wartość domyślną, BATCHNUMjeśli użytkownik jej nie podał:

: "${BATCHNUM:=3}"
Cuonglm
źródło
4
[ -n "$BATCHNUM" ] || { kill "$PPID"; exit 1; }
#Unless $BATCHNUM is defined and unempty, ask parent process to exit and exit w/ 1

Działa to w trybie bash i POSIX sh. Wolę nie rozróżniać pustych zmiennych od niezdefiniowanych zmiennych (tzn. Nie lubięset -u , ale to tylko ja).

PSkocik
źródło
2

Linie

if [ -z "$BATCHNUM" ]; then
    exit 2;
fi

sprawdź, czy jest pusty $BATCHNUM. Dzięki $PPIDniemu możesz wyrządzić rodzicowi krzywdę, jaką chcesz (kill $PPID ). Aby zamordować dziadka, musisz uzyskać identyfikator procesu w inny sposób, na przykład patrząc na dane /proc/$PPID.

Jeśli jednak twój rodzic umiera, wysyła ci sygnał ( SIGHUP), więc musisz go złapać, zanim zaczniesz zabijać kogokolwiek:

trap '' SIGHUP

Aktualizacja: Jeśli uważasz, że musisz zabić rodziców, robisz to źle. Po prostu zwróć znaczący kod wyjścia. Skrypt nadrzędny powinien sprawdzić kod powrotu wywoływanego skryptu i odpowiednio zareagować.

Thomas Erker
źródło
1
trochę brutalne .... :)
user40780
1

Aby sprawdzić, czy BATCHNUMjest zdefiniowane i wyjść, jeśli nie jest:

if [ -n "${BATCHNUM-a}" ]; then
  echo >&2 "Fatal error: BATCHNUM not set"
  exit 2
fi

Jeśli chcesz również odrzucić skrzynkę, w której BATCHNUMjest pusta, użyj ${BATCHNUM:+a}zamiast ${BATCHNUM+a}. Aby uzyskać informacje na temat ${VARIABLE+TEXT_IF_NULL}konstrukcji rozszerzenia parametru, patrz np . Instrukcja bash .

Nie zabijaj procesu nadrzędnego. Nie wiesz, co to jest proces nadrzędny. Jeśli jakiś skrypt, który go wywołuje, musi przerwać działanie, jeśli ten skrypt zostanie przerwany, spraw, aby sprawdził status wyjścia tego skryptu. Np. W skrypcie nr 2:

script3 || exit $?

lub użyj, set -eaby przerwać skrypt, jeśli dowolne polecenie zwróci status błędu (niezerowy).

Gilles „SO- przestań być zły”
źródło