Ловушка ошибок bash из дочернего скрипта

#bash #bash-trap

#bash #bash-trap

Вопрос:

Я вызываю скрипт bash (скажем child.sh ) в моем скрипте bash (скажем parent.sh ), и я хотел бы, чтобы ошибки в script ( child.sh ) попали в мой родительский скрипт ( parent.sh ).

Я прочитал статью medium и сообщение stack exchange. Исходя из этого, я подумал, что мне следует сделать set -E с моим родительским скриптом, чтобы ЛОВУШКИ наследуются вспомогательной оболочкой. Соответственно, мой код выглядит следующим образом

parent.sh

 #!/bin/bash
  
set -E

error() {
  echo -e "$0: e[0;33mERROR: The Zero Touch Provisioning script failed while running the command $BASH_COMMAND at line $BASH_LINENO.e[0m" >amp;2
  exit 1
}

trap error ERR
./child.sh
  

child.sh

 #!/bin/bash
ls -al > /dev/null
cd non_exisiting_dir #To simulate error
echo "$0: I am still continuing after error"
  

Вывод

 ./child.sh: line 5: cd: non_exisiting_dir: No such file or directory
./child.sh: I am still continuing after error
  

Не могли бы вы сообщить мне, чего мне не хватает, чтобы я мог наследовать ловушки, определенные в родительском скрипте.

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

1. Я не могу воспроизвести это в оболочке Linux bash. Если вы находитесь в другой среде, добавьте это в вопрос.

2. Я попробовал это в одном из экземпляров EC2. GNU bash, version 4.2.46(2)-release это моя версия bash.

3. @VivekMaran: Если вы хотите child.sh прервать выполнение команд, выдающих ненулевой код выхода, вы можете просто выполнить set -e .

Ответ №1:

./child.sh не выполняется в «подоболочке».

Подоболочка — это не дочерний процесс вашей оболочки, который тоже является оболочкой, а специальная среда, в которой выполняются команды изнутри (...) $(...) или, ...|... что обычно реализуется путем разветвления текущей оболочки без выполнения другой оболочки.

Если вы хотите работать child.sh в подоболочке, то исходите из этого скрипта из подоболочки, которую вы можете создать с помощью (...) :

 (. ./child.sh)
  

который унаследует вашу ERR ловушку из-за set -E .

Примечания:

Есть и другие места, где bash выполняет команды в подоболочке: процесс замены ( <(...) ), сопроцессы, command_not_found_handle функция и т. Д.

В некоторых оболочках (но не в bash) крайняя левая команда из конвейера не выполняется в подоболочке. Например ksh -c ':|a=2; echo $a' , будет выведено 2. Кроме того, не все оболочки реализуют подоболочки путем разветвления отдельного процесса.

Даже если bash печально известен тем, что позволяет экспортировать функции в другие скрипты bash через среду (с export -f funcname помощью ), это AFAIK невозможно с ловушками 😉