Я пишу сценарий оболочки, и мне нужно проверить, установлено ли терминальное приложение. Я хочу использовать команду TRY / CATCH, чтобы сделать это, если нет более аккуратного способа.
bash
shell
error-handling
Ли Проберт
источник
источник
help test
может помочь вам найти решение вашей проблемы.trap
команды.Ответы:
Нет.
Bash не так много предметов роскоши, как можно найти во многих языках программирования.
Нет
try/catch
в bash; однако, можно добиться аналогичного поведения, используя&&
или||
.Использование
||
:если
command1
не получается,command2
работает следующим образомТочно так же, используя
&&
,command2
будет работать, еслиcommand1
успешноНаиболее близким приближением
try/catch
является следующееТакже bash содержит некоторые механизмы обработки ошибок, а также
он останавливает ваш сценарий, если любая простая команда терпит неудачу.
А также почему бы и нет
if...else
. Это твой лучший друг.источник
#save your output
не работал, иначе блок «catch» все равно будет выполняться.if...else
конструкцию. Означает ли это, что команды bash считаются «правдивыми», если они выполняются успешно, и «ложными», если они терпят неудачу?set -e
это не обязательно лучший способ сделать что-то; Вот некоторые контраргументы / особые случаи: mywiki.wooledge.org/BashFAQ/105Основываясь на некоторых ответах, которые я нашел здесь, я сделал себе небольшой вспомогательный файл для источника моих проектов:
trycatch.sh
Вот пример того, как это выглядит при использовании:
источник
||
послеcatch
и до{}
блока? Я бы подумал, что это&&
if False or run_if_failed()
означает, что короткое замыкание ИЛИ попыталось выполнить первое утверждение, которое не вернуло истину, и теперь переходит к следующему утверждению.&&
не будет работать, потому что первый оператор (try
) выдал false, что означает, чтоcatch
по правилу тавтологии утверждение не является необходимымfalse&any equals false
. Только не короткое замыкание И / ИЛИ будет выполнять оба.Я разработал почти безупречную реализацию try & catch в bash, которая позволяет вам писать такой код:
Вы можете даже вложить блоки try-catch внутри себя!
Код является частью моего bash шаблон / рамки . Это дополнительно расширяет идею try & catch с такими вещами, как обработка ошибок с обратным следом и исключениями (плюс некоторые другие приятные функции).
Вот код, который отвечает только за try & catch:
Не стесняйтесь использовать, раскошелиться и внести свой вклад - это на GitHub .
источник
my_output=$(try { code...; } catch { code...; })
Вы можете использовать
trap
:try { block A } catch { block B } finally { block C }
переводится как:
источник
-E
флаг, я думаю, поэтому ловушка распространяется на функцииЕсть так много похожих решений, которые, вероятно, работают. Ниже приведен простой и эффективный способ выполнить попытку / поймать с пояснениями в комментариях.
источник
bash
не прерывает выполнение в случае, если что-то обнаруживает состояние ошибки (если вы не установите-e
флаг). Языки программирования, которые предлагаютtry/catch
это, делают это для того, чтобы предотвратить «спасение» из-за этой особой ситуации (поэтому ее обычно называют «исключением»).В
bash
, вместо этого, только команда в вопросе выйдет с кодом выхода Большого чем 0, что указывает на состояние ошибки. Вы можете проверить , что, конечно, но так как нет никакого автоматического откачка из ничего, попробовать / поймать не имеет смысла. Просто не хватает этого контекста.Однако вы можете смоделировать спасение, используя вспомогательные оболочки, которые могут завершиться в точке, которую вы решите:
Вместо этого
some_condition
сif
вы также можете просто попробовать команду, и в случае , если он не может (имеет Greater выход кода , чем 0), выручать:К сожалению, используя эту технику, вы ограничены 255 различными кодами выхода (1..255), и никакие достойные объекты исключений не могут быть использованы.
Если вам нужно больше информации для передачи с вашим смоделированным исключением, вы можете использовать стандартный вывод подоболочек, но это немного сложнее и, возможно, другой вопрос ;-)
Используя вышеупомянутый
-e
флаг для оболочки, вы можете даже удалить это явноеexit
утверждение:источник
Как все говорят, bash не имеет надлежащего поддерживаемого языка синтаксиса try / catch. Вы можете запустить bash с
-e
аргументом или использоватьset -e
внутри скрипта, чтобы прервать весь процесс bash, если какая-либо команда имеет ненулевой код завершения. (Вы такжеset +e
можете временно разрешить сбой команд.)Итак, один из методов для имитации блока try / catch - запуск подпроцесса для выполнения работы с
-e
включенным. Затем в основном процессе проверьте код возврата подпроцесса.Bash поддерживает строки heredoc, поэтому вам не нужно писать два отдельных файла для этого. В приведенном ниже примере TRY heredoc будет выполняться в отдельном экземпляре bash с
-e
включенным, поэтому подпроцесс завершится сбоем, если какая-либо команда вернет ненулевой код завершения. Затем, вернувшись в основной процесс, мы можем проверить код возврата для обработки блока catch.Это не правильный поддерживаемый языком блок try / catch, но он может поцарапать подобный зуд для вас.
источник
Ты можешь сделать:
источник
И у вас есть ловушки http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html, который отличается от других, но другой метод, который вы можете использовать для этой цели
источник
Очень простая вещь, которую я использую:
источник
||
находится внутри()
, она будет работать в подоболочке и выходить, не вызывая выхода из основной оболочки.{ }
Вместо этого используйте группировку.Ниже приведена полная копия упрощенного сценария, используемого в моем другом ответе . Помимо дополнительной проверки ошибок, существует псевдоним, который позволяет пользователю изменять имя существующего псевдонима. Синтаксис приведен ниже. Если
new_alias
параметр не указан, псевдоним удаляется.Полный сценарий приведен ниже.
источник
Ниже приведен пример скрипта, который реализуется
try/catch/finally
в bash.Примеры сценариев начинаются с создания анонимного fifo, который используется для передачи строковых сообщений от
command exception
илиthrow
до конца ближайшегоtry
блока. Здесь сообщения удаляются из fifo и помещаются в переменную массива. Статус возвращается черезreturn
иexit
команд и помещены в другой переменной. Чтобы войти вcatch
блок, этот статус не должен быть нулевым. Другие требования для вводаcatch
блока передаются в качестве параметров. Еслиcatch
достигнут конец блока, то статус устанавливается на ноль. Еслиfinally
достигнут конец блока и статус все еще не равен нулю, выполняется неявный выброс, содержащий сообщения и статус. Сценарий требует вызова функции,trycatchfinally
которая содержит необработанный обработчик исключений.Синтаксис
trycatchfinally
команды приведен ниже.-c
Опция добавляет стек вызовов для сообщений исключений. Опция позволяет отладочный вывод. Опция позволяет исключения команд. Опция позволяет пользователю заменить свой собственный обработчик команды исключения. Опция добавляет стек вызовов к выходу отладки. Опция заменяет выходной файл по умолчанию , который . Опция позволяет пользователю заменить свое собственное необработанное обработчик исключений. Опция позволяет пользователю возможности передавать обратно значение , хотя использование команды подстановки. Это имя файла fifo. Функция вызывается как подпроцесс.-d
-e
-h
-k
-o
/dev/fd/2
-u
-v
fifo
function
trycatchfinally
Синтаксис
catch
команды приведен ниже.Варианты определены ниже. Значением для первого списка является статус. Последующие значения - это сообщения. Если сообщений больше, чем списков, оставшиеся сообщения игнорируются.
-e
означает[[ $value == "$string" ]]
(значение должно соответствовать хотя бы одной строке в списке)-n
означает[[ $value != "$string" ]]
(значение не может соответствовать ни одной из строк в списке)-o
означает[[ $value != $pattern ]]
(значение не может соответствовать ни одной из шаблонов в списке)-p
означает[[ $value == $pattern ]]
(значение имеет сопоставить хотя бы один шаблон в списке)-r
означает[[ $value =~ $regex ]]
(значение должно соответствовать хотя бы одному расширенному регулярному выражению в списке)-t
означает[[ ! $value =~ $regex ]]
(значение не может соответствовать ни одному из расширенных регулярных выражений в списке)try/catch/finally
Сценарий приводится ниже. Чтобы упростить сценарий для этого ответа, большая часть проверки ошибок была удалена. Это уменьшило размер на 64%. Полную копию этого сценария можно найти в моем другом ответе .Ниже приведен пример, в котором предполагается, что вышеуказанный скрипт хранится в файле с именем
simple
.makefifo
Файл содержит скрипт , описанный в этом ответе . Предполагается, что названный файл4444kkkkk
не существует, поэтому возникает исключение. Вывод сообщения об ошибке изls 4444kkkkk
команды автоматически подавляется до тех пор, пока внутри соответствующегоcatch
блока.Вышеуказанный скрипт был протестирован с использованием
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. Результат выполнения этого скрипта показан ниже.Другой пример, который использует a,
throw
можно создать, заменив функциюMyFunction3
скриптом, показанным ниже.Синтаксис
throw
команды приведен ниже. Если параметры отсутствуют, вместо них используются статус и сообщения, хранящиеся в переменных.Результат выполнения модифицированного скрипта показан ниже.
источник