Можно ли использовать «set -e», но разрешить сбой определенных команд?

#bash #sh #zsh

#bash #sh #zsh

Вопрос:

Я работаю над сценарием резервного копирования и хотел бы остановить сценарий при ошибке, за исключением определенных команд, таких как veracrypt --mount , которые возвращают 1, когда они уже смонтированы.

 #! /bin/sh

set -e

veracrypt --text --mount --pim 0 --keyfiles "" --protect-hidden no "/Volumes/Samsung BAR/.b" /Volumes/Backup

borg check /Volumes/Backup/Borg

veracrypt --text --dismount "$BACKUP_VOLUME_PATH"
  

Ответ №1:

Вы можете использовать || для выполнения чего-то, что не завершится неудачей в случае сбоя основной команды, например, с:

 blah || true
{ yada; yada; yada; } || true
  

Без || true скрипт будет жаловаться на ошибку, а затем остановится. При этом вы все равно увидите ошибку, но сценарий будет продолжен.


Другая возможность заключается в использовании того факта, что это не считается сбоем, если это часть if :

 if blah ; then true ; fi
  

Даже если blah ошибки, сценарий будет продолжен.


Наконец, вы можете временно отключить его для определенной команды:

 set  e ; blah ; set -e
  

Это решение действительно работает, только если вы уже знаете текущую настройку. Вы, вероятно, не хотите включать -e , если он не был установлен до того, как вы его выключили.

Чтобы определить текущую настройку и снова включить ее, только если она уже была включена заранее, вы можете использовать:

 # 1: State here can be either  e or -e. If -e, record that fact and make  e.

eWasSet=false; [[ $- = *e* ]] amp;amp; eWasSet=true amp;amp; set  e

# 2: Do stuff that needs  e.

blah blah blah

# 3: Revert state if needed. After this, it's as it was in comment 1 above.

${eWasSet} amp;amp; set -e
  

Это работает, потому что $- содержит все текущие set значения (например, ehB для вывода ошибки, хеширования и расширения фигурных скобок), поэтому вы можете использовать операторы равенства с подстановочными знаками, чтобы узнать, активен ли определенный параметр (например, e ).

Комментарии:

1. Также можно set e отключить выход при сбое, а затем снова включить с помощью set -e . Полезно, когда следует несколько команд.

2. Другой метод, использующий блок : { foo ; bar ; baz ;} || true

3. @EdouardThiel Интересно! Почему-то я думал, что set -e должен быть установлен в верхней части скрипта и не может быть переключен впоследствии.