W skrypcie Bash Jak mogę zamknąć cały skrypt, jeśli wystąpi określony warunek?

Piszę skrypt w Bash, aby przetestować jakiś kod. Jednak, wydaje się głupie, aby uruchomić testy, jeśli skompilowanie kodu nie powiedzie się w pierwszej kolejności, w takim przypadku po prostu przerwać testy.

Czy jest jakiś sposób, aby to zrobić bez zawijania całego skryptu wewnątrz pętli while I używania przerw? Coś w stylu dun dun dun goto?

Author: Peter Mortensen, 2009-09-04

6 answers

Spróbuj tego stwierdzenia:

exit 1

Zastąp 1 odpowiednimi kodami błędów. Patrz również kody wyjścia ze specjalnymi znaczeniami .

 522
Author: Michael Foukarakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-07 07:10:15

Użyj set-e

#!/bin/bash

set -e

/bin/command-that-fails
/bin/command-that-fails2

Skrypt zakończy się po pierwszej linii, która się nie powiedzie (zwraca niezerowy kod zakończenia). W tym przypadku polecenie command-that-fails2 nie zostanie uruchomione.

Jeśli miałbyś sprawdzić status powrotu każdego polecenia, Twój skrypt wyglądałby tak:

#!/bin/bash

# I'm assuming you're using make

cd /project-dir
make
if [[ $? -ne 0 ]] ; then
    exit 1
fi

cd /project-dir2
make
if [[ $? -ne 0 ]] ; then
    exit 1
fi

Z set-e wyglądałoby to następująco:

#!/bin/bash

set -e

cd /project-dir
make

cd /project-dir2
make

Każde polecenie, które się nie powiedzie, spowoduje błąd całego skryptu i zwróci status zakończenia, który możesz sprawdzić za pomocą $?. Jeśli twój skrypt jest bardzo długi lub budujesz wiele rzeczy, będzie to dość brzydkie, jeśli dodasz wszędzie sprawdzanie statusu zwrotu.

 565
Author: Shizzmo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-24 20:11:01

Zły SysOps facet kiedyś nauczył mnie techniki Trzypalcowych pazurów:

yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "cannot $*"; }

Te funkcje są * Nix OS i Shell flavor-solidne. Umieść je na początku skryptu (bash lub w inny sposób), try() twoje oświadczenie i Kod na.

Wyjaśnienie

(na podstawie latające Owce komentarz).

  • yell: wypisuje nazwę skryptu i wszystkie argumenty na stderr:
    • $0 jest ścieżką do skryptu;
    • $* to wszystkie argumenty.
    • >&2 oznacza > przekierowanie stdout do & rury 2. rura 1 byłoby stdout samym sobą.
  • die robi to samo co yell, ale wychodzi z non-0 status wyjścia , co oznacza "nie powiodło się".
  • try używa || (boolean OR), który ocenia tylko prawą stronę, jeśli lewa nie zawiedzie.
    • $@ to znowu wszystkie argumenty, aleInne .

Hope that explains wszystko.

 163
Author: c.gutierrez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:31

Jeśli wywołasz skrypt z source, możesz użyć return <x> Gdzie <x> będzie statusem zakończenia skryptu(użyj niezerowej wartości dla error lub false). Będzie to również działać zgodnie z oczekiwaniami, gdy skrypt source. Jeśli wywołasz skrypt wykonywalny (tzn. bezpośrednio z jego nazwą pliku), Instrukcja return spowoduje skargę (komunikat o błędzie "return: can only `return' from a function or sourced script").

Jeśli zamiast tego zostanie użyty exit <x>, gdy skrypt zostanie wywołany z source, będzie spowoduje to wyjście powłoki, która uruchomiła skrypt, ale skrypt wykonywalny będzie działał bezpośrednio w porządku.

Do obsługi obu przypadków w tym samym skrypcie, możesz użyć

return <x> 2> /dev/null || exit <x>

Poradzi sobie z każdym odpowiednim wywołaniem.

Uwaga: <x> ma być tylko liczbą.

 15
Author: kavadias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-12 15:22:58

Często dołączam funkcję run () do obsługi błędów. Każde wywołanie, które chcę wykonać, jest przekazywane do tej funkcji, więc cały skrypt kończy się po wystąpieniu błędu. Zaletą tego rozwiązania w stosunku do set-e jest to, że skrypt nie kończy się po cichu, gdy linia zawiedzie, i może powiedzieć, na czym polega problem. W poniższym przykładzie trzecia linia nie jest wykonywana, ponieważ skrypt kończy się przy wywołaniu false.

function run() {
  cmd_output=$(eval $1)
  return_value=$?
  if [ $return_value != 0 ]; then
    echo "Command $1 failed"
    exit -1
  else
    echo "output: $cmd_output"
    echo "Command succeeded."
  fi
  return $return_value
}
run "date"
run "false"
run "date"
 9
Author: velotron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-18 19:21:51

Zamiast if konstruuj, możesz wykorzystać Ocena zwarcia :

#!/usr/bin/env bash

echo $[1+1]
echo $[2/0]              # division by 0 but execution of script proceeds
echo $[3+1]
(echo $[4/0]) || exit $? # script halted with code 1 returned from `echo`
echo $[5+1]

Zwróć uwagę na parę nawiasów, które są niezbędne ze względu na priorytet operatora alternacji. $? jest specjalną zmienną ustawioną na kod zakończenia ostatnio wywołanego polecenia.

 5
Author: skalee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-04 12:35:39