Bash-функции игнорируют set -e - PullRequest
0 голосов
/ 10 июня 2018

Как я могу запустить функцию как "проверенную команду" и выполнить действие при сбое, все еще прерывая функцию, как только возникает ошибка?Рассмотрим следующий скрипт:

#!/bin/bash -e

function foo() {
   echo Entering foo
   false
   echo Should not reach this line
}

foo || echo I want to see this line on failure in foo
foo

Вывод, который я получаю:

Entering foo
Should not reach this line
Entering foo

Хотя я хотел бы получить

Entering foo
I want to see this line on failure in foo
Entering foo

Я думаю, что япоиск - это способ пометить функцию как непроверенную команду.Согласно man-странице bash

 -e errexit
         Exit immediately if any untested command fails in non-interactive
         mode.  The exit status of a command is considered to be explicitly
         tested if the command is part of the list used to control an if,
         elif, while, or until; if the command is the left hand operand of
         an “&&” or “||” operator; or if the command is a pipeline preceded
         by the ! operator.  If a shell function is executed and its exit
         status is explicitly tested, all commands of the function are con‐
         sidered to be tested as well.

EDIT Ожидаемый результат был неверным.отредактировал это для ясности

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Я закончил оборачивать код, чтобы сделать это в служебной функции ниже.

#!/bin/bash -e

# Runs given code aborting on first error and taking desired action on failure
# $1 code to invoke, can be expression or function name
# $2 error handling code, can be function name or expressions
function saferun {
  set +e
  (set -E ; trap 'exit 1' ERR ; eval $1) 
  [ $? -ne 0 ] && eval $2
  set -e
}

function foo() {
   echo Entering foo
   false
   echo Should not reach this line
}

saferun foo "echo I want to see this line on failure in foo"
foo

Давайте разберем это:

  • set +e и set -e используютсядля подавления сбоя при ошибке, так как в противном случае скрипт просто завершится при первой ошибке
  • trap используется для прерывания выполнения при любой ошибке (вместо set -e) () используется для запуска заданнойкод в подоболочке, поэтому внешний скрипт будет продолжать работать после сбоя, а set -E используется для передачи ловушки в подоболочку.поэтому (set -E ; trap 'exit 1' ERR ; eval $1) запускает данный код / ​​функцию, прерывающуюся при первой ошибке, не выходя из всего сценария
  • $? -ne 0 проверяет наличие ошибок и eval $2 запускает код обработки ошибок
0 голосов
/ 10 июня 2018

set -e отключен при первом вызове foo, поскольку он находится слева от ||.

Кроме того, вы никогда не увидите выводимой строки I want to see this ..., если толькопоследний echo в foo как-то не удался (именно этот последний echo в foo определяет статус выхода функции).

foo() {
    echo Entering foo
    false && echo Should not reach this line
}

foo || echo I want to see this line on failure in foo
foo

Вышеуказанные выходы (с set -x или без него))

Entering foo
I want to see this line on failure in foo
Entering foo

Теперь false - последний выполненный оператор в foo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...