Существуют ли стандартные коды состояния выхода в 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.
Заметки
Несколько ответов определяют статус выхода 2 как "Неправильное использование встроенных команд bash". Это применимо только тогда, когда bash (или скрипт bash) выходит со статусом 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 other 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
.