В Linux считается, что процесс завершился правильно, если его статус завершения был равен 0. Я видел, что ошибки сегментации часто приводят к статусу завершения 11, хотя я не знаю, является ли это просто традицией там, где я работаю (приложения, которые вызвали ошибку таким образом, что все они были внутренними), или стандартом. Существуют ли стандартные коды завершения процессов в Linux?
Ответ 1
8 бит кода возврата и 8 бит номера сигнала завершения смешиваются в одно значение при возврате из wait(2)...
#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("первый процесс вышел с кодом %u\n", WEXITSTATUS(status));
child = fork();
if (child <= 0)
kill(getpid(), SIGSEGV);
waitpid(child, &status, 0);
if (WIFSIGNALED(status))
printf("второй процесс вышел с кодом %u\n", WTERMSIG(status));
}
Как вы определяете статус выхода? Традиционно оболочка хранит только 8-битный код возврата, но устанавливает старший бит, если процесс был ненормально завершен.
$ sh -c 'exit 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Segmentation fault
139
$ expr 139 - 128
11
Если вы видите что-то другое, то, вероятно, программа имеет обработчик сигнала SIGSEGV, который затем нормально вызывает exit, так что на самом деле он не завершается этим сигналом (программы могут выбирать обработку любых сигналов, кроме SIGKILL и SIGSTOP).
Ответ 2
Часть 1: Расширенное руководство по сценариям Bash
1: Подборка общих ошибок
2: Неправильное использование встроенных модулей оболочки (согласно документации Bash)
126: Вызванная команда не может быть выполнена
127: "команда не найдена"
128: Неверный аргумент для выхода
128+n: Сигнал фатальной ошибки "n"
255: Статус выхода вне диапазона (exit принимает только целочисленные аргументы в диапазоне 0–255)
Часть 2: sysexits.h
В Linux:
$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h
/*
#define EX_OK 0 /* успешное завершение */
#define EX__BASE 64 /* базовое значение для сообщений об ошибках */
#define EX_USAGE 64 /* ошибка использования командной строки */
#define EX_DATAERR 65 /* ошибка формата данных */
#define EX_NOINPUT 66 /* не возможно отрыть входной поток */
#define EX_NOUSER 67 /* неизвестный адрес */
#define EX_NOHOST 68 /* неизвестное имя хоста */
#define EX_UNAVAILABLE 69 /* сервис недоступен */
#define EX_SOFTWARE 70 /* внутренняя ошибка программного обеспечения */
#define EX_OSERR 71 /* системная ошибка */
#define EX_OSFILE 72 /* отсутствует критический файл ОС */
#define EX_CANTCREAT 73 /* не удается создать выходной файл */
#define EX_IOERR 74 /* ошибка ввода/вывода */
#define EX_TEMPFAIL 75 /* временный отказ; пользователю предлагается повторить попытку */
#define EX_PROTOCOL 76 /* удаленная ошибка в протоколе данных */
#define EX_NOPERM 77 /* отказано в доступе */
#define EX_CONFIG 78 /* ошибка конфигурации */
#define EX__MAX 78 /* превышено максимальное значение */
Ответ 3
Ни один из предыдущих ответов не описывает состояние выхода правильно. Вопреки тому, что они утверждают, статус 2 — это то, что на самом деле возвращают ваши утилиты командной строки при неправильном вызове. Вот реальное правило, которое ранее было принято как соглашение о статусе выхода для нормального завершения, т. е. не по сигналу:
Статус выхода 0: успех
Статус выхода 1: "ошибка", как определено программой
Статус выхода 2: ошибка использования командной строки
Например, diff возвращает 0, если сравниваемые файлы идентичны, и 1, если они различаются. По давней традиции, программы unix возвращают статус выхода 2 при неправильном вызове (неизвестные опции, неправильное количество аргументов и т. д.). Например, diff -N, grep -Y или diff a b c приведут к тому, что $? будет установлен в 2. Это практика с первых дней существования Unix, начиная с 1970-х годов.
Принятый ответ объясняет, что происходит, когда команда завершается по сигналу. Вкратце, завершение из-за непойманного сигнала приводит к статусу выхода 128+[<номер сигнала>. Например, завершение по сигналу SIGINT (сигнал 2) приводит к статусу выхода 130.
Примечания:
В некоторых ответах статус выхода 2 определяется как "Неправильное использование встроенных модулей bash". Это применимо только тогда, когда bash (или сценарий bash) завершается со статусом 2. Считайте это частным случаем ошибки неправильного использования. В файле sysexits.h, упомянутом в прежнем ответе, статус выхода EX_USAGE ("ошибка использования командной строки") определен как 64. Но это не отражает реальности ситуации. Я не знаю ни одной распространенной утилиты Unix, которая при неправильном вызове возвращает 64. Внимательное чтение исходного кода показывает, что sysexits.h является скорее желанием, чем отражением истинного использования.
Ответ 4
В первом приближении 0 — это успех, ненулевое значение — это ошибка, причем 1 — это общая ошибка, а все, что больше единицы, — это ошибка, определяемая конкретной ситуацией. Кроме тривиальных исключений false и test, которые оба предназначены для того, чтобы давать 1 за успех, есть еще несколько исключений для данного случая. Более реалистично: 0 означает успех или, возможно, ошибку (в некоторых случаях); 1 означает общую ошибку или, возможно, успех; 2 означает общую ошибку. Команда diff выдает 0, если сравниваемые файлы идентичны, 1 — если они различаются, и 2 — если двоичные файлы различны. 2 также означает ошибку. Команда less выдает 1 при ошибке, если вы не указали аргумент, в этом случае она завершается с 0, несмотря на ошибочную ситуацию.
Команда more и команда spell выдают 1 при ошибке, если только они не являются результатом отказа в разрешении, несуществующего файла или попытки чтения каталога. В любом из этих случаев они выдают 0, несмотря опять-таки на ошибку. Затем команда expr выдает 1 за успех, если на выходе не пустая строка или ноль, в этом случае 0 — успех, 2 и 3 — ошибка.
Затем есть случаи, когда успех или ошибка неоднозначны. Если grep не смог найти шаблон, он выдает 1, но при некоторых ошибках (например, при отказе в разрешении) выдает 2. Klist также выдает 1, когда ему не удается найти ответ, хотя на самом деле это не большая проблема, чем когда grep не находит шаблон или когда вы входите командой ls в пустой каталог. Так что, к сожалению, в unix, похоже, нет какого-либо логического набора правил, даже для очень часто используемых исполняемых файлов.
Linux