Существуют ли стандартные коды состояния выхода в Linux? - PullRequest
286 голосов
/ 09 июля 2009

Процесс считается правильно завершенным в Linux, если его состояние выхода было 0.

Я видел, что ошибки сегментации часто приводят к состоянию выхода 11, хотя я не знаю, является ли это просто соглашением, в котором я работаю (приложения, которые потерпели неудачу, как все, были внутренними) или стандартом.

Существуют ли стандартные коды выхода для процессов в Linux?

Ответы [ 10 ]

327 голосов
/ 08 октября 2009

Часть 1: Руководство по расширенному написанию сценариев Bash

Как всегда, Расширенное руководство по написанию сценариев Bash содержит полезную информацию : (Это было связано в другом ответе, но с неканоническим URL.)

1: Catchall для общих ошибок
2: Неправильное использование встроенных командных оболочек (согласно документации Bash)
126: Вызванная команда не может быть выполнена
127:"команда не найдена"
128: Недопустимый аргумент для выхода
128 + n: Сигнал фатальной ошибки "n"
255: Выход из состояния вне диапазона (выход принимает только целочисленные аргументы в диапазоне 0 - 255)

Часть 2: sysexits.h

Ссылки ABSG sysexits.h.

В Linux:

$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h

/*
 * Copyright (c) 1987, 1993
 *  The Regents of the University of California.  All rights reserved.

 (A whole bunch of text left out.)

#define EX_OK           0       /* successful termination */
#define EX__BASE        64      /* base value for error messages */
#define EX_USAGE        64      /* command line usage error */
#define EX_DATAERR      65      /* data format error */
#define EX_NOINPUT      66      /* cannot open input */    
#define EX_NOUSER       67      /* addressee unknown */    
#define EX_NOHOST       68      /* host name unknown */
#define EX_UNAVAILABLE  69      /* service unavailable */
#define EX_SOFTWARE     70      /* internal software error */
#define EX_OSERR        71      /* system error (e.g., can't fork) */
#define EX_OSFILE       72      /* critical OS file missing */
#define EX_CANTCREAT    73      /* can't create (user) output file */
#define EX_IOERR        74      /* input/output error */
#define EX_TEMPFAIL     75      /* temp failure; user is invited to retry */
#define EX_PROTOCOL     76      /* remote error in protocol */
#define EX_NOPERM       77      /* permission denied */
#define EX_CONFIG       78      /* configuration error */

#define EX__MAX 78      /* maximum listed value */
83 голосов
/ 09 июля 2009

8 битов кода возврата и 8 битов номера сигнала убийства смешиваются в одно значение при возврате из wait(2) & co. .

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>

int main() {
    int status;

    pid_t child = fork();
    if (child <= 0)
        exit(42);
    waitpid(child, &status, 0);
    if (WIFEXITED(status))
        printf("first child exited with %u\n", WEXITSTATUS(status));
    /* prints: "first child exited with 42" */

    child = fork();
    if (child <= 0)
        kill(getpid(), SIGSEGV);
    waitpid(child, &status, 0);
    if (WIFSIGNALED(status))
        printf("second child died with %u\n", WTERMSIG(status));
    /* prints: "second child died with 11" */
}

Как вы определяете статус выхода? Традиционно оболочка хранит только 8-битный код возврата, но устанавливает старший бит, если процесс был ненормально завершен.

$ sh -c 'exit 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Segmentation fault
139
$ expr 139 - 128
11

Если вы видите что-то кроме этого, то, вероятно, программа имеет обработчик сигнала SIGSEGV, который затем обычно вызывает exit, так что сигнал фактически не убивается. (Программы могут выбрать обработку любых сигналов, кроме SIGKILL и SIGSTOP.)

70 голосов
/ 09 июля 2009

'1' >>> Catchall для общих ошибок

'2' >>> Неправильное использование встроенных командных оболочек (согласно документации Bash)

'126' >>> Вызванная команда не может быть выполнена

'127' >>> "команда не найдена"

'128' >>> Недопустимый аргумент для выхода

'128 + n' >>> Сигнал фатальной ошибки "n"

'130' >>> Сценарий прекращен с помощью Control-C

'255' >>> Выход из состояния вне диапазона

Это для bash. Однако для других приложений существуют разные коды выхода.

47 голосов
/ 08 ноября 2016

Ни один из более старых ответов не описывает правильное состояние выхода 2. Вопреки тому, что они утверждают, status 2 - это то, что утилиты командной строки фактически возвращают при неправильном вызове. (Да, ответ может быть девять лет, иметь сотни голосов и все же ошибаться.)

Вот реальное, давнее соглашение о статусе выхода для нормального завершения, т.е. не по сигналу:

  • Статус выхода 0: успех
  • Состояние выхода 1: «сбой», как определено программой
  • Состояние выхода 2: ошибка использования командной строки

Например, diff возвращает 0, если сравниваемые файлы идентичны, и 1, если они различаются. По давним соглашениям программы Unix возвращают выход из состояния 2 при неправильном вызове (неизвестные параметры, неправильное количество аргументов и т. в $? установлен на 2. Это и было практикой с первых дней Unix в 1970-х.

В принятом ответе объясняется, что происходит, когда команда завершается сигналом. Вкратце, завершение из-за отсутствия сигнала приводит к состоянию выхода 128+[<signal number>. Например, завершение по SIGINT ( сигнал 2 ) приводит к состоянию выхода 130.

Примечания

  1. В нескольких ответах статус выхода 2 определяется как «Неправильное использование встроенных команд bash». Это применимо только тогда, когда bash (или сценарий bash) выходит со статусом 2. Считайте, что это особый случай неправильной ошибки использования.

  2. В sysexits.h, упомянутом в самом популярном ответе , состояние выхода EX_USAGE («ошибка использования командной строки») определено равным 64. Но это не отражает реальность: я не знаю какой-либо общей утилиты Unix, которая возвращает 64 при неправильном вызове (примеры приветствуются). Внимательное прочтение исходного кода показывает, что sysexits.h является желательным, а не отражением истинного использования:

     *    This include file attempts to categorize possible error
     *    exit statuses for system programs, notably delivermail
     *    and the Berkeley network.
    
     *    Error numbers begin at EX__BASE [64] to reduce the possibility of 
     *    clashing with oth­er exit statuses that random programs may 
     *    already return. 
    

    Другими словами, эти определения не отражают общепринятую практику того времени (1993 г.), но намеренно несовместимы с ней. Больше жаль.

23 голосов
/ 09 июля 2009

Стандартных кодов выхода нет, кроме 0, означающего успех. Ненулевое значение также не обязательно означает отказ.

stdlib.h определяет EXIT_FAILURE как 1 и EXIT_SUCCESS как 0, но это все.

11 на segfault интересен, так как 11 - это номер сигнала, который ядро ​​использует для уничтожения процесса в случае segfault. Вероятно, существует какой-то механизм, либо в ядре, либо в оболочке, который преобразует его в код выхода.

20 голосов
/ 09 июля 2009

sysexits.h содержит список стандартных кодов выхода. Похоже, он датируется как минимум 1993 годом, и некоторые крупные проекты, такие как Postfix, используют его, поэтому я думаю, что это путь.

Со страницы руководства OpenBSD:

Согласно стилю (9), не рекомендуется вызывать exit (3) с значения trary для обозначения состояния отказа при завершении программы. В- вместо этого следует использовать заранее определенные коды выхода из сисекситов, поэтому вызывающий процесс может получить приблизительную оценку о классе отказа без поиска исходного кода.
8 голосов
/ 10 июня 2015

В первом приближении 0 - это успех, ненулевое - это сбой, 1 - общий сбой, а все, что больше, - конкретный сбой. Помимо тривиальных исключений false и test, которые предназначены для получения 1 за успех, я обнаружил еще несколько исключений.

Более реалистично, 0 означает успех или неудачу, 1 означает общий сбой или успех, 2 означает общий отказ, если 1 и 0 оба используются для успеха, но, возможно, также и успех.

Команда diff дает 0, если сравниваемые файлы идентичны, 1, если они различаются, и 2, если двоичные файлы различны. 2 также означает неудачу. Команда less дает 1 для сбоя, если только вы не ввели аргумент, в этом случае он выходит из 0, несмотря на сбой.

Команда more и команда spell дают 1 для сбоя, если сбой не является результатом отказа в доступе, несуществующего файла или попытки прочитать каталог. В любом из этих случаев они выходят из 0 несмотря на ошибку.

Тогда команда expr выдает 1 для sucess, если только выводом является пустая строка или ноль, в этом случае 0 - это sucess. 2 и 3 - сбой.

Тогда есть случаи, когда успех или неудача неоднозначны. Когда grep не удается найти шаблон, он выходит из 1, но выходит из 2 для подлинного сбоя (например, отказано в разрешении). Klist также завершает работу с 1, когда не удается найти заявку, хотя это на самом деле не более, чем ошибка, когда grep не находит шаблон или когда вы пустой каталог.

Так что, к сожалению, возможности Unix, по-видимому, не приводят в исполнение какой-либо логический набор правил, даже для очень часто используемых исполняемых файлов.

5 голосов
/ 09 июля 2009

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

Как этот код выхода назначается переменной состояния $? затем до оболочки. Bash сохраняет младшие 7 бит состояния и затем использует 128 + (номер сигнала) для индикации сигнала.

Единственное «стандартное» соглашение для программ - 0 для успеха, ненулевое для ошибки. Другое используемое соглашение - возвращать errno при ошибке.

3 голосов
/ 09 июля 2009

Стандартные коды выхода Unix определяются sysexits.h, как упоминалось в другом постере. Такие же коды выхода используются переносимыми библиотеками, такими как Poco - вот их список:

http://pocoproject.org/docs/Poco.Util.Application.html#16218

Сигнал 11 является сигналом SIGSEGV (нарушение сегмента), который отличается от кода возврата. Этот сигнал генерируется ядром в ответ на неправильный доступ к странице, что приводит к завершению программы. Список сигналов можно найти на странице справки по сигналам (запустите «сигнал человека»).

2 голосов
/ 09 июля 2009

Когда Linux возвращает 0, это означает успех. Все остальное означает сбой, каждая программа имеет свои коды выхода, поэтому было бы довольно долго перечислять их все ...!

Что касается кода ошибки 11, то это действительно номер ошибки сегментации, в основном это означает, что программа получила доступ к области памяти, которая не была назначена.

...