Чи є стандартні коди статусу виходу в Linux?


308

Вважається, що процес завершено правильно в Linux, якщо його вихідний статус був 0.

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

Чи є стандартні коди виходу для процесів в Linux?


6
якщо ви шукаєте те, що називається "номер системної помилки", повернене системними функціями, дивіться тут на errno
marinara

Відповіді:


86

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'; ехо $?
42
$ sh -c 'вбити -SEGV $$'; ехо $?
Помилка сегментації
139
$ expr 139 - 128
11

Якщо ви бачите щось, окрім цього, програма, ймовірно, має SIGSEGVобробник сигналу, який потім дзвонить exitнормально, тому насправді це не вбивається сигналом. (Програми можуть обрати будь-які сигнали, окрім SIGKILLі SIGSTOP.)


8
З огляду на те, як зараз постає запитання, це не є найбільш корисною (і таким чином прийнятою) відповіддю.
Девід Дж.

332

Частина 1: Розширений посібник із написання сценарію

Як завжди, в Посібнику з розширеного сценарію розширених даних є чудова інформація : (Це було пов’язано в іншій відповіді, але з некононічною URL-адресою.)

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

Частина 2: сисексит.ч

Посилання на 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 */

5
Зауважте, що в деяких ароматах unix деякі команди використовують статус виходу 2 для позначення інших речей. Наприклад, багато реалізацій grep використовують статус виходу 2, щоб вказати на помилку, і використовують статус виходу 1, щоб означати, що не було знайдено вибраних рядків.
NamshubWriter

3
На BSD є чоловіча сторінка, яка підбиває інформацію з sysexits.h:man sysexits
georgebrock

6
Що сказав @NamshubWriter Вихід 2 - це універсальний перехід для неправильного використання командного рядка в утилітах Unix, не лише в "деяких ароматах unix", але і взагалі. Заголовок, показаний у цій відповіді, не відображає фактичних умов, ні зараз, ні коли він був написаний у 1987 році.
alexis

АБС не "чудовий". Будь ласка, прочитайте на цю тему; критику знайти не зовсім важко.
трійка

Але де власне офіційний вихідний код sysexits.h? Сторінка чоловіка, на яку всі посилаються, - це просто проза. Наприклад, він посилається, EX_OKале насправді не визначає його нормативно, як інші коди. Чи є ще якісь відсутні?
Гаррет Вілсон

71

'1' >>> Catchall для загальних помилок

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

'126' >>> Команда, що викликається, не може виконати

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

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

'128 + n' >>> Сигнал про помилку "n"

'130' >>> Сценарій, що припиняється Control-C

'255' >>> Вихід із поза діапазону

Це для баш. Однак для інших програм існують різні коди виходу.


1
Схоже, ви обоє відповіли в одну і ту ж хвилину. Тіану доведеться досить швидко побачити ваші посилання та вставити їх.
Натан Феллман

6
Зауважте, що "контроль-C дає 130" відповідає "128 + n" для сигналу n; control-C породжує SIGINT, який є сигналом 2.
Джонатан Леффлер

3
Це здається плагіатом із АБС без атрибуції. (Ми можемо сказати, тому що АБС містить неправдиву або хоча б оманливу інформацію.)
tripleee

4
Це ЗАБЕЗПЕЧЕННІ коди виходу, відповідно до Посібника з розширеного сценарію . Це означає, що цих значень слід уникати для визначених користувачем параметрів виходу .
ingyhere

53

Жодна з старих відповідей не описує статус виходу 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 script) виходить зі статусом 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 р.), Але навмисно несумісні з нею. Більше шкода.


Що потрібна програма повернення , коли він робить припинення ручки ловлячи SIGINT / Ctrl-C? Ще 130? Чи має значення інша оболонка, крім башти?
Gringo Suave

1
Оболонка, яка виконує програму, не має значення; процес теоретично міг вибрати вихід із різним статусом залежно від його батьківського процесу, але я ніколи не чув про випадок, коли це відбувається.
alexis

1
Якщо програма наздоганяє SIGINT, очищає та виходить із нього все одно, стан є будь-яким сенсом для програми. Наприклад, moreбуде скинутий термінальний режим і вийти зі статусом 0 (можна спробувати).
alexis

1
Ця відповідь передбачає набагато вищий ступінь стандартизації, ніж те, що є насправді. Немає належної стандартизації значення значення 2, і фактична практика тоді передбачувано дуже неоднозначна. Це правда, що багато інструментів повертають 2 за неправильне використання, але це не зовсім точно визначено, що означає "неналежне використання", і багато інших не дотримуються цієї конвенції.
трійка

@tripleee "інструменти" також недостатньо визначені! :-) Звичайно, кожен може написати програму командного рядка, і вона може взагалі повернути що завгодно, але старі школи "Утиліти командного рядка Unix", які існували довше, ніж Linux, або вміст основних програм GNU - цілком послідовно в цьому. Якщо ви думаєте про інше, будь ласка, назвіть деякі інструменти в цій групі, які не використовують статус 2 таким чином. Крім того, "неналежне використання" - це ваш термін (і я згоден, що це невиразний термін); Я написав "помилку використання командного рядка", яка є досить специфічною: неіснуючі або несумісні параметри, неправильна кількість аргументів, що не є опцією, тощо.
alexis

25

Стандартних кодів виходу немає, окрім 0, що означає успіх. Ненульовий не обов'язково означає і збій.

stdlib.h визначає EXIT_FAILUREяк 1 іEXIT_SUCCESS як 0, але це про це.

11 на segfault цікаво, оскільки 11 - номер сигналу, який ядро ​​використовує для вбивства процесу у випадку сегмента за замовчуванням. Ймовірно, якийсь механізм, або в ядрі, або в оболонці, який переводить його у вихідний код.


20

сисексит.х має перелік стандартних кодів виходу. Здається, вона сягає щонайменше 1993 року, і деякі великі проекти, такі як Postfix, використовують її, тому я думаю, що це шлях.

На головній сторінці OpenBSD:

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

8

До першого наближення 0 - це успіх, не нуль - це збій, 1 - загальний збій, а все, що більше, ніж одне - конкретний збій. Окрім тривіальних винятків помилок та тесту, які розроблені таким чином, щоб дати успіх 1, я знайшов кілька інших винятків.

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

Команда diff дає 0, якщо порівняні файли однакові, 1 якщо вони відрізняються, і 2, якщо двійкові файли відрізняються. 2 також означає збій. Команда менше дає 1 за відмову, якщо ви не введете аргумент, і в цьому випадку він виходить з 0, незважаючи на невдачу.

Команда "Більше" та "Заклинання" дають 1 за помилку, якщо тільки помилка не є результатом дозволу, відхиленого, неіснуючого файлу або спроби прочитати каталог. У будь-якому з цих випадків вони виходять з 0, незважаючи на збій.

Тоді команда expr дає 1 для успіху, якщо вихід не є порожнім рядком або нулем, і в цьому випадку 0 є успішним. 2 і 3 - відмова.

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

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


Я збирався також зазначити поведінку дифу. wget також має детальні помилки (наприклад, 6 для помилки аутентифікації), але тоді вони використовують 1 = загальну помилку, 2..n = питома помилка
PypeBros

5

Програми повертають 16-бітний код виходу. Якщо програма була вбита сигналом, то байт високого порядку містить використаний сигнал, інакше байт низького порядку - це статус виходу, повернутий програмістом.

Як цей вихідний код присвоюється змінній статусу $? то до оболонки. Bash зберігає нижні 7 біт статусу, а потім використовує 128 + (сигнал nr) для вказівки сигналу.

Єдиний "стандартний" режим для програм - 0 для успіху, не нульовий для помилок. Ще одна умова, що використовується - це повернення errno на помилку.


3

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

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

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


1

Коли Linux повертає 0, це означає успіх. Все інше означає збій, у кожної програми є свої вихідні коди, тому перераховувати їх було б досить довго ...!

Щодо 11 помилок, це дійсно номер помилки сегментації, головним чином означає, що програма отримала доступ до місця, яке не було призначено.


1
Це завжди 11, тому що ядро ​​вбиває його і призначає "значення виходу". Так само й інші типи несправностей завжди отримуватимуть однакове значення виходу.
Алекс Гартрелл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.