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

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

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

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

12 ответов

Решение

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 'выход 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Ошибка сегментации
139
$ expr 139 - 128
11

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

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

Как всегда, в Advanced Bash Scripting Guide есть много полезной информации: (Это было связано с другим ответом, но с неканоническим 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 */

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

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

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

Например, diff возвращает 0, если сравниваемые файлы идентичны, и 1, если они различаются. По давним соглашениям программы Unix возвращают статус выхода 2 при неправильном вызове (неизвестные параметры, неправильное количество аргументов и т. Д.). Например, diff -N, grep -Y или же diff a b c все приведет к $? устанавливается на 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 г.), но намеренно несовместимы с ней. Больше жалости.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

В первом приближении 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-возможности, похоже, не реализуют какой-либо логический набор правил, даже для очень часто используемых исполняемых файлов.

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

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

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

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

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

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

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

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

Ниже вы можете просмотреть список распространенных кодов завершения для сценариев оболочки Linux. Ниже прикреплена ссылка для получения дополнительной информации: Надеюсь, это поможет кому-то быстро отладить.

      0   Success
1   Operation not permitted
2   No such file or directory
3   No such process
4   Interrupted sys
5   Input/output error
6   No such device or address
7   Argument list too long
8   Exec format error
9   Bad file descriptor
10  No child processes
11  Resource temporarily unavailable
12  Cannot allocate memory
13  Permission denied
14  Bad address
15  Block device required
16  Device or resource busy
17  File exists
18  Invalid cross-device link
19  No such device
20  Not a directory
21  Is a directory
22  Invalid argument
23  Too many open files in system
24  Too many open files
25  Inappropriate ioctl for device
26  Text file busy
27  File too large
28  No space left on device
29  Illegal seek
30  Read-only file system
31  Too many links
32  Broken pipe
33  Numerical argument out of domain
34  Numerical result out of range
35  Resource deadlock avoided
36  File name too long
37  No locks available
38  Function not implemented
39  Directory not empty
40  Too many levels of symbolic links
42  No message of desired type
43  Identifier removed
44  Channel number out of range
45  Level 2 not synchronized
46  Level 3 halted
47  Level 3 reset
48  Link number out of range
49  Protocol driver not attached
50  No CSI structure available
51  Level 2 halted
52  Invalid exchange
53  Invalid request descriptor
54  Exchange full
55  No anode
56  Invalid request code
57  Invalid slot
59  Bad font file format
60  Device not a stream
61  No data available
62  Timer expired
63  Out of streams resources
64  Machine is not on the network
65  Package not installed
66  Object is remote
67  Link has been severed
68  Advertise error
69  Srmount error
70  Communication error on send
71  Protocol error
72  Multihop attempted
73  RFS specific error
74  Bad message
75  Value too large for defined data type
76  Name not unique on network
77  File descriptor in bad state
78  Remote address changed
79  Can not access a needed shared library
80  Accessing a corrupted shared library
81  .lib section in a.out corrupted
82  Attempting to link in too many shared libraries
83  Cannot exec a shared library directly
84  Invalid or incomplete multibyte or wide character
85  Interrupted system call should be restarted
86  Streams pipe error
87  Too many users
88  Socket operation on non-socket
89  Destination address required
90  Message too long
91  Protocol wrong type for socket
92  Protocol not available
93  Protocol not supported
94  Socket type not supported
95  Operation not supported
96  Protocol family not supported
97  Address family not supported by protocol
98  Address already in use
99  Cannot assign requested address
100 Network is down
101 Network is unreachable
102 Network dropped connection on reset
103 Software caused connection abort
104 Connection reset by peer
105 No buffer space available
106 Transport endpoint is already connected
107 Transport endpoint is not connected
108 Cannot send after transport endpoint shutdown
109 Too many references
110 Connection timed out
111 Connection refused
112 Host is down
113 No route to host
114 Operation already in progress
115 Operation now in progress
116 Stale file handle
117 Structure needs cleaning
118 Not a XENIX named type file
119 No XENIX semaphores available
120 Is a named type file
121 Remote I/O error
122 Disk quota exceeded
123 No medium found
125 Operation canceled
126 Required key not available
127 Key has expired
128 Key has been revoked
129 Key was rejected by service
130 Owner died
131 State not recoverable
132 Operation not possible due to RF-kill
133 Memory page has hardware error

https://www.cyberciti.biz/faq/linux-bash-exit-status-set-exit-statusin-bash/

Некоторые из них являются условными, но некоторые другие зарезервированные являются частью стандарта POSIX.

126 -- Файл для выполнения найден, но это не исполняемая утилита.

127 -- Утилита для выполнения не найдена.

>128 -- Команда была прервана сигналом.

См . раздел ОБОСНОВАНИЕman 1p exit.

Другие вопросы по тегам