Есть ли способ написать функцию bash, которая прерывает все выполнение, независимо от того, как оно вызывается? - PullRequest
67 голосов
/ 27 марта 2012

Я использовал инструкцию «exit 1» в моих функциях bash, чтобы завершить весь скрипт, и он работал нормально:

function func()
{
   echo "Goodbye"
   exit 1
}
echo "Function call will abort"
func
echo "This will never be printed"

Но потом я понял, что он не работает, когда вызывается как:

res=$(func)

Я понимаю, что создал подоболочку, и "выход 1" прерывает эту подоболочку, а не основную ....

Но есть ли способ написать функцию, которая прерывает все выполнение, независимо от того, как она вызывается? Мне просто нужно получить реальное возвращаемое значение (повторяется функцией).

Ответы [ 5 ]

79 голосов
/ 27 марта 2012

Что вы могли бы сделать, это зарегистрировать оболочку верхнего уровня для выхода сигнала TERM, а затем отправить TERM оболочке верхнего уровня:

#!/bin/bash
trap "exit 1" TERM
export TOP_PID=$$

function func()
{
   echo "Goodbye"
   kill -s TERM $TOP_PID
}

echo "Function call will abort"
echo $(func)
echo "This will never be printed"

Итак, ваша функция отправляет сигнал TERM обратно в оболочку верхнего уровня, которая перехватывается и обрабатывается с помощью предоставленной команды, в данном случае "exit 1".

33 голосов
/ 27 марта 2012

Вы можете использовать set -e, который выходит, если команда выходит с ненулевым статусом :

set -e 
func
set +e

Или получите возвращаемое значение:

(func) || exit $?
1 голос
/ 27 марта 2012

Но есть ли способ написать функцию, которая прерывает все выполнение, независимо от того, как она вызывается?

Нет.

Мне просто нужно получитьреальное возвращаемое значение (повторяется функцией).

Вы можете

res=$(func)
echo $?
0 голосов
/ 19 июня 2019

Наверное, лучше это

#!/bin/bash
set -e
trap "exit 1" ERR

myfunc() {
     set -x # OPTIONAL TO SHOW ERROR
     echo "Exit with failure"
     set +x # OPTIONAL
     exit 1
}
echo "BEFORE..."
myvar="$(myfunc)"
echo "AFTER..But not shown"
0 голосов
/ 27 марта 2012

Дочерний процесс не может принудительно закрыть родительский процесс.Вам нужно использовать какой-то механизм сигнализации.Опции могут включать в себя специальное возвращаемое значение или, возможно, отправку некоторого сигнала с kill, например,

function child() {
    local parent_pid="$1"
    local other="$2"
    ...
    if [[ $failed ]]; then
        kill -QUIT "$parent_pid"
    fi
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...