Родительский скрипт продолжается, когда ребенок выходит с ненулевым кодом выхода

У меня есть сценарий, который вызывает другой скрипт. Когда дочерний скрипт терпит неудачу, я хотел бы, чтобы родительский сбой также не удался.

В дочернем скрипте child_1.sh меня есть что-то вроде этого:

 if [ $SOME_BAD_CONDITION ] ; then echo "Error message...." exit 1 fi 

У родителя у меня есть следующее:

 #!/bin/bash set -e #... bash ./child_1.sh echo "continuing to next step..." bash ./child_2.sh bash ./child_3.sh #... 

Я настроил свою среду таким образом, чтобы всегда $SOME_BAD_CONDITION , и сценарий завершается так, как ожидалось, и сообщение об ошибке печатает, но родительский скрипт продолжается: $SOME_BAD_CONDITION сообщение «continue …», и следующий скрипт начинает выполнение ,

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

версия bash: 4.2.25


ОБНОВИТЬ:

Я пробовал эхом $? :

 bash ./child_1.sh echo $? echo "continuing to next step..." 

Результат выглядит следующим образом:

 Сообщение об ошибке....
 0
 продолжая следующий шаг ...

Почему код выхода из ребенка не попадает в родительский?


ОТВЕТ: Исходный фрагмент кода был неполным. exit 1 находился внутри кодового блока, который был подключен к тройнику. Моя попытка опубликовать чистый, короткий пример кода проигнорировала это, потому что я не понимал, насколько это значимо (я все еще довольно новичок в bash-скриптах). Для получения более подробной информации см. Мой ответ.

  • Сценарий оболочки Linux удаляет определенное содержимое в файле
  • Как я могу запустить этот скрипт python во всех html-файлах под каталогом?
  • Как я могу выбрать один из результатов поиска и разрешить его открытие с помощью указанного приложения
  • Косая черта, не обнаруженная в команде «grep»
  • Предсказывать имя файла перед загрузкой с URL-адреса, в сценарии оболочки
  • Копирование / переименование нескольких файлов с использованием регулярного выражения (сценарий оболочки)
  • OS / X: невозможно выполнить сценарии оболочки - выдает новое окно, которое немедленно выйдет
  • Использование Grep In For Loop
  • 3 Solutions collect form web for “Родительский скрипт продолжается, когда ребенок выходит с ненулевым кодом выхода”

    Так как ваш дочерний процесс завершает работу с надлежащим нулевым / ненулевым кодом выхода, и если вы выполняете их последовательно, я бы сказал, что вы можете просто использовать оператор && :

     #!/bin/bash ./child_1.sh [[ $? -ne 0 ]] && exit # Exit if non-zero exit code ./child_2.sh ./child_3.sh ./child_4.sh exit 0 

    Здесь [[ $? -ne 0 ]] && exit [[ $? -ne 0 ]] && exit :

     if [ $? -ne 0 ]; then # If: last exit code is non-zero exit fi 

    Если вам нечего делать между вызовами, вы даже можете использовать …

     #!/bin/bash ./child_1.sh && ./child_2.sh && ./child_3.sh && ./child_4 exit $? 

    Оператор && действует как оператор короткого замыкания AND , а нулевой код выхода в значительной степени похож на true булево значение. Если в любой момент в цепочке сценарий завершается с ненулевым значением, то && будет терпеть неудачу, и сценарии с подпоследователями не должны вызываться.

    Таким образом, я, возможно, допустил ошибку, не размещая достаточно подробностей о дочернем скрипте – я упростил ее для этого вопроса, но, возможно, слишком много. Оператор exit был похоронен внутри кодового блока (между { и } ), который был запрограммирован на tee для ведения журнала:

     { #... if [ $SOME_BAD_CONDITION ] ; then exit 1 fi #... } | tee -a $LOGFILE echo "script ended at $date">>$LOGFILE 

    Из того, что я понимаю, у меня всегда был код возврата 0 из этого дочернего скрипта, потому что последнее echo возвращалось 0. Я провел некоторое исследование и обнаружил $ PIPESTATUS . Я смог использовать это, чтобы гарантировать, что когда мой скрипт попытается выйти с кодом выхода 1, он будет передан родительскому скрипту:

     { #... } | tee -a $LOGFILE EXIT_CODE=${PIPESTATUS[0]} echo "script ended at $date">>$LOGFILE exit $EXIT_CODE 

    В сочетании с предложением Джона у меня есть решение, которое, кажется, работает.

    Похоже, ваша проблема проистекает из того, как вы выбрасываете ошибку в своем дочернем скрипте.

    Из набора людей «если простая команда (см. SHELL GRAMMAR выше) выходит с ненулевым статусом. Оболочка не выходит, если неудавшаяся команда является частью списка команд сразу после некоторого времени или пока ключевое слово, часть теста в выражении if, в части списка && или ||, или если возвращаемое значение команды перевернулось через! "

    Вместо использования set -e используйте оператор trap и выдайте ошибку. (Если вам нужно использовать условный выход.

    См. http://mywiki.wooledge.org/BashFAQ/105

    Interesting Posts

    Использование PAM, как минимальное количество дней между изменениями пароля установлено?

    ClamAV: подавляет весь вывод, кроме сводных

    Как заставить CLI работать на выделенной графике?

    Как исправить частые сбои openhot?

    Сбой сценария резервного копирования с параметрами команды rsync в цитируемой переменной

    Автоответчик для OPENSSL с использованием HEREDOC

    переключиться на пользователя sudo с командой AND не работает

    Удалить файлы из списка, которые были созданы / изменены в субботу

    Определить качество сигнала или уровень сигнала через hostapd или iw

    Как запустить сценарий во время выхода из системы GNOME, если у меня нет прав администратора?

    IPC: уведомление об отключенной общей памяти

    На LMDE 2, почему мой экран отключается через несколько секунд?

    Почему мой зашифрованный том LVM (устройство LUKS) не будет монтироваться во время загрузки?

    Заменить отсутствующие шрифты в OpenOffice

    init: /etc/init.conf: Не удается загрузить конфигурацию: нет такого файла или каталога

    Linux и Unix - лучшая ОС в мире.