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

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

Ответ 1

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

ls somefile
echo $?

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

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

Ответ 3

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

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

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

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

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

Подробнее см. Bash Руководство по программированию.

Ответ 4

Пример минимального состояния выхода POSIX C

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

В Linux:

  • когда процесс вызывает системный вызов 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

Ответ 5

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

Ответ 6

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

Ответ 7

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

Пример

command1 && command2 && command3

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

Ответ 8

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

Ответ 9

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