it-swarm.com.ru

Что такое $? (доллар вопросительный знак) переменная в сценариях оболочки?

Я пытаюсь изучить сценарии Shell, и мне нужно понять чужой код. Что такое переменная $?? Я не могу Google найти ответ, потому что они блокируют знаки препинания.

229
David Mulder

$? используется для поиска возвращаемого значения последней выполненной команды. Попробуйте следующее в командной консоли:

ls somefile
echo $?

Если somefile существует (независимо от того, является ли он файлом или каталогом), вы получите возвращаемое значение, выданное командой ls, которое должно быть 0 (возвращаемое значение по умолчанию "success"). Если он не существует, вы должны получить число, отличное от 0. Точное число зависит от программы.

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

219
pooamlairaj

Это статус выхода последней выполненной функции/программы/команды. Ссылаться на:

45
Dor

Возвращаемое значение ранее выполненного процесса.

10.4 Получение возвращаемого значения программы

В bash возвращаемое значение программы хранится в специальной переменной с именем $ ?.

Это иллюстрирует, как захватить возвращаемое значение программы, я предполагаю, что каталог Дада не существует. (Это было также предложено Майком)

        #!/bin/bash
        cd /dada &> /dev/null
        echo rv: $?
        cd $(pwd) &> /dev/null
        echo rv: $?

Смотрите Руководство по программированию Bash для более подробной информации.

18
user405725

$? является результатом (код выхода) последней выполненной команды.

9
marcelog

Пример минимального C

Чтобы понять $?, вы должны сначала понять концепцию завершения процесса.

В Linux:

  • когда процесс вызывает системный вызов exit, ядро ​​сохраняет значение, переданное системному вызову, даже после смерти процесса.

    Системный вызов exit вызывается функцией ANSI C exit() и косвенно при выполнении return из main.

  • процесс, который вызвал выходящий дочерний процесс (Bash), часто с fork + exec, может получить состояние завершения дочернего процесса с помощью системного вызова wait

Рассмотрим код Bash:

$ false
$ echo $?
1

C "эквивалент" это:

false.c:

#include <stdlib.h> /* exit */

int main() {
    exit(1);
}

bash.c:

#include <unistd.h> /* execl */
#include <stdlib.h> /* fork */
#include <sys/wait.h> /* wait, WEXITSTATUS */
#include <stdio.h> /* printf */

int main() {
    if (fork() == 0) {
        /* Call false. */
        execl("./false", "./false", (char *)NULL);
    }
    int status;
    /* Wait for a child to finish. */
    wait(&status);
    /* Status encodes multiple fields,
     * we need WEXITSTATUS to get the exit status:
     * http://stackoverflow.com/questions/3659616/returning-exit-code-from-child
     **/
    printf("$? = %d\n", WEXITSTATUS(status));
}

В Bash, когда вы нажимаете Enter, происходит форк + exec + wait, как описано выше, а затем bash устанавливает $? в состояние завершения разветвленного процесса.

Примечание: для встроенных команд, таких как echo, процесс не нужно вызывать, и Bash просто устанавливает $? в 0 для имитации внешнего процесса.

Стандарты и документация

POSIX 7 2.5.2 "Специальные параметры" http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02 :

? Расширяется до десятичного состояния выхода самого последнего конвейера (см. Конвейеры).

man bash "Специальные параметры":

Оболочка обрабатывает несколько параметров специально. На эти параметры можно ссылаться только; присвоение им не допускается. [...]

? Расширяется до состояния выхода последнего выполненного переднего конвейера.

Затем ANSI C и POSIX рекомендуют:

  • 0 означает, что программа была успешной

  • другие значения: программа как-то не удалась.

    Точное значение может указывать тип отказа.

    ANSI C не определяет значение каких-либо значений, а POSIX определяет значения больше 125: я так и не понял: что такое POSIX?

Bash использует статус выхода для if

В Bash мы часто неявно используем статус выхода $? для управления операторами if, как в:

if true; then
  :
fi

где true - это программа, которая просто возвращает 0.

Вышеуказанное эквивалентно:

true
result=$?
if [ $result = 0 ]; then
  :
fi

И в:

if [ 1 = 1 ]; then
  :
fi

[ - это просто программа со странным именем (и встроенный в Bash, который ведет себя так же, как и он), и 1 = 1 ] ее аргументы, см. также: В чем разница между одинарными и двойными квадратными скобками в Bash?

$? - это состояние завершения команды, так что вы можете последовательно соединять ряд команд.

пример

command1 && command2 && command3

command2 будет запущен, если command1's$? даст success (0) и command3 будет выполнен, если $? из command2 выдаст success

4
Glenn John Ogapong

Это возвращенный код ошибки последней выполненной команды. 0 = успех

4
Wulf

Он хорошо подходит для отладки в случае выхода из скрипта, если используется set -e. Например, поместите echo $? после команды, которая заставляет его выйти и увидеть возвращаемое значение ошибки.

2
lukmac

Код выхода последней команды выполнен.

2
Matt