5

Разница между return и exit в функциях Bash

14

В чем разница между return и exit в функциях Bash с точки зрения кодов завершения?

5 ответ(ов)

4

Функция return [n] в Bash останавливает выполнение функции и возвращает значение, указанное параметром n, вызывающему коду. Если этот параметр опущен, возвращается код состояния последней выполненной команды в теле функции.

С другой стороны, команда exit [n] завершает выполнение оболочки с кодом состояния n. Если n не указан, код выхода будет равен коду состояния последней выполненной команды. Примечание: перед завершением оболочки выполняется команда, определенная с помощью trap на событие EXIT.

EDIT:

Что касается кодов выхода, команда return не имеет отношения к кодам выхода. Коды выхода предназначены для приложений/скриптов, а не для функций. Таким образом, единственное ключевое слово, которое устанавливает код выхода скрипта (который может быть захвачен вызывающей программой через переменную $?), — это exit.

EDIT 2:

Мое предыдущее утверждение о exit вызвало несколько комментариев. Оно было сделано для того, чтобы различить return и exit для лучшего понимания вопроса. На самом деле, на любом этапе выполнения программы/скрипта, exit — это единственный способ завершить скрипт с кодом выхода для вызывающего процесса.

Каждая команда, выполняемая в оболочке, производит локальный «код выхода»: он устанавливает переменную $? в этот код и может использоваться с if, && и другими операторами для условного выполнения других команд.

Эти коды выхода (и значение переменной $?) сбрасываются при каждом выполнении команды.

Кстати, код выхода последней выполненной командой в скрипте используется как код выхода самого скрипта, как это видно вызывающим процессом.

В конечном итоге функции, при вызове, ведут себя как команды оболочки в отношении кодов выхода. Код выхода функции (внутри функции) устанавливается с помощью команды return. Таким образом, когда в функции выполняется return 0, выполнение функции завершается с кодом выхода 0.

3

Функция return приводит к тому, что текущая функция выходит из области видимости, в то время как exit завершает выполнение скрипта в точке, где она была вызвана. Вот пример программы, который поможет это объяснить:

#!/bin/bash

retfunc()
{
    echo "это retfunc()"
    return 1
}

exitfunc()
{
    echo "это exitfunc()"
    exit 1
}

retfunc
echo "Мы все еще здесь"
exitfunc
echo "Мы никогда не увидим это"

Вывод

$ ./test.sh
это retfunc()
Мы все еще здесь
это exitfunc()

В этом примере, когда вызывается retfunc, она выполняет свою работу и возвращает управление назад, позволяя продолжать выполнение скрипта, что позволяет вывести "Мы все еще здесь". Однако, когда вызывается exitfunc, она завершает выполнение всего скрипта, и строка "Мы никогда не увидим это" никогда не будет выполнена.

0

Разница между операторами return и exit в функциях Bash относительно кодов завершения действительно очень мала. Оба возвращают статус, но не значения в привычном смысле. Статус 0 указывает на успешное выполнение, в то время как любой другой статус (от 1 до 255) говорит о сбое. Оператор return возвращает управление в скрипт, откуда была вызвана функция, тогда как оператор exit завершает весь скрипт, где бы он ни находился.

Вот примеры:

return 0  # Возвращает в место вызова функции.  $? содержит 0 (успех).

return 1  # Возвращает в место вызова функции.  $? содержит 1 (сбой).

exit 0    # Полностью завершает скрипт.  $? содержит 0 (успех).

exit 1    # Полностью завершает скрипт.  $? содержит 1 (сбой).

Если ваша функция просто завершается без оператора return, статус последней выполненной команды будет возвращён в качестве кода завершения (и окажется в $?).

Помните, что операторы return и exit возвращают коды статуса от 0 до 255, доступные в $?. Вы не можете передать что-либо другое через код статуса (например, return "cat"); это не сработает. Однако скрипт может вернуть 255 различных причин сбоя, используя коды статуса.

Вы можете устанавливать переменные, находящиеся в вызывающем скрипте, или использовать echo в функции и затем подменять результаты в вызывающем скрипте; но цель операторов return и exit — передавать коды статуса, а не значения или результаты вычислений, как это можно ожидать в языках программирования, таких как C.

0

При выполнении скрипта с помощью . или source, например:

. a.sh

Если в a.sh будет команда exit, это приведёт не только к завершению выполнения скрипта, но и к окончанию вашей сессии в оболочке.

С другой стороны, если в a.sh использовать return, то это просто остановит выполнение скрипта, и ваша оболочка продолжит работать.

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

0

Вопрос от автора: Какова разница между операторами return и exit в функциях BASH с точки зрения кодов выхода?

Прежде всего, необходимо прояснить несколько моментов:

  • Операторы (return|exit) не обязательны для завершения выполнения (функции|шелла). (Функция|Шелл) завершится, когда достигнет конца своего списка кода, даже без оператора (return|exit).

  • Операторы (return|exit) не обязательны для передачи значения обратно от завершившейся (функции|шелла). Каждый процесс имеет встроенную переменную $?, которая всегда содержит числовое значение. Это специальная переменная, которую нельзя установить напрямую, например, "?=1"; она устанавливается только особым образом (см. ниже *).

    Значение $? после последней выполняемой команды в (вызванной функции | подсистеме) — это значение, которое передается обратно (вызвавшей функции | родительскому шеллу). Это верно, независимо от того, была ли последней выполненной командой ("return [n]"| "exit [n]") или простая ("return" или что-то еще, что оказалось последней командой в коде вызванной функции.

В приведенном выше списке выберите из "(x|y)" либо всегда первый пункт, либо всегда второй, чтобы получить утверждения о функциях и return, или о шеллах и exit соответственно.

Ясно, что оба оператора используют специальную переменную $? для передачи значений вверх после завершения.

  • Теперь о специальных способах, которыми можно установить $?:
  • Когда вызванная функция завершает выполнение и возвращается к своему вызывающему, тогда $? в вызывающем будет равен итоговому значению $? в завершившейся функции.
  • Когда родительский шелл явно или неявно ожидает завершения одной подсистемы и освобождается после ее завершения, то $? в родительском шелле будет равно итоговому значению $? в завершившейся подсистеме.
  • Некоторые встроенные функции могут изменять $? в зависимости от своего результата. Но некоторые этого не делают.
  • Встроенные функции "return" и "exit", когда за ними следует числовой аргумент, устанавливают $? на свое значение аргумента и завершают выполнение.

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

# (exit 259)
# echo $?
3
Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь