В сценарии Bash, как я могу выйти из всего сценария, если возникает определенное условие?
Я пишу сценарий в Bash, чтобы проверить некоторый код. Однако кажется глупым запускать тесты, Если компиляция кода не выполняется в первую очередь, и в этом случае я просто прерву тесты.
есть ли способ сделать это без обертывания всего сценария внутри цикла while и использования перерывов? Что-то вроде Дун Дун Дун Гото?
6 ответов:
попробуйте это заявление:
exit 1заменить
1с соответствующими кодами ошибок. Смотрите также Коды Завершения, Имеющие Предопределенный Смысл.
использовать set-e
#!/bin/bash set -e /bin/command-that-fails /bin/command-that-fails2скрипт завершится после первой строки, которая завершится неудачно (возвращает ненулевой код выхода). В этом случае command-that-fails2 не будет работать.
если бы вы проверяли состояние возврата каждой отдельной команды, ваш скрипт выглядел бы так:
#!/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С set-e это будет выглядеть так:
#!/bin/bash set -e cd /project-dir make cd /project-dir2 makeлюбая команда, которая терпит неудачу, приведет к сбою всего сценария и верните статус выхода, который вы можете проверить с помощью $?. Если ваш скрипт очень длинный или вы создаете много вещей, это будет довольно уродливо, если вы добавите проверки состояния возврата везде.
один мерзкий Сисоп однажды научил меня технике трехпалого Когтя:
yell() { echo ": $*" >&2; } die() { yell "$*"; exit 111; } try() { "$@" || die "cannot $*"; }эти функции * ОС Никс и вкус раковины-крепкий. Поставил их в начале вашего скрипта (bash или иначе),
try()ваш оператор и код ВКЛ.объяснение
(исходя из летающих овец комментарий).
yell: выведите имя скрипта и все аргументы вstderr:
- это путь к скрипту ;$*все аргументы.>&2означает>перенаправить stdout в & pipe2. труба1будетstdoutсам по себе.dieделает то же самое, что иyell, но выходит с не-0 статус выхода, что означает "потерпеть неудачу".tryиспользует||(булевоOR), который оценивает только правую сторону, если левая не подвел.
$@это все аргументы снова, но разные.надеюсь, что это все объясняет.
если вы вызовете скрипт с
source, вы можете использоватьreturn <x>здесь<x>будет состояние выхода скрипта (используйте ненулевое значение для error или false). Это также будет работать, как ожидалось, когда выsourceсценарий. Если вы вызываете исполняемый сценарий (т. е. непосредственно с его именем файла), оператор return приведет к жалобе (сообщение об ошибке "return: может только"return" из функции или исходного сценария").если
exit <x>используется вместо этого, когда вызывается скрипт сsource, это приведет к выходу из оболочки, которая запустила скрипт, но исполняемый скрипт будет работать непосредственно нормально.для обработки любого случая в том же скрипте, вы можете использовать
return <x> 2> /dev/null || exit <x>это будет обрабатывать любой вызов может быть подходящим.
Примечание:
<x>- это должно быть просто число.
Я часто включаю функцию run () для обработки ошибок. Каждый вызов, который я хочу сделать, передается этой функции, поэтому весь скрипт завершается при сбое. Преимущество этого по сравнению с решением set-e заключается в том, что скрипт не выходит беззвучно при сбое строки и может рассказать вам, в чем проблема. В следующем примере 3-я строка не выполняется, потому что сценарий завершается при вызове false.
function run() { cmd_output=$(eval ) return_value=$? if [ $return_value != 0 ]; then echo "Command failed" exit -1 else echo "output: $cmd_output" echo "Command succeeded." fi return $return_value } run "date" run "false" run "date"
вместо
ifпостроить, Вы можете использовать оценка короткого замыкания:#!/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]обратите внимание на пару скобок, которая необходима из-за приоритета оператора чередования.
$?- это переменная недавно выход из кода команды.