Linux中是否有任何标准的退出状态代码?

Nat*_*man 300 linux error-handling exit-code

如果进程的退出状态为0,则认为该进程已在Linux中正确完成.

我已经看到分段错误经常导致退出状态为11,但我不知道这是否只是我工作的惯例(那些失败的应用程序都是内部的)或标准.

Linux中的进程是否有标准退出代码?

Sch*_*hof 327

第1部分:高级Bash脚本编写指南

与往常一样,Advanced Bash Scripting Guide提供了很多信息 :(这是在另一个答案中链接的,但是与非规范URL相关联.)

1: 一般错误的捕获
2:错误使用shell内置函数(根据Bash文档)
126: 调用的命令无法执行
127: "未找到命令"
128: 退出
128 + n的参数无效: 致命错误信号"n"
255:退出状态超出范围(退出只接受0到255范围内的整数args)

第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 */
Run Code Online (Sandbox Code Playgroud)

  • @NamshubWriter说的是什么.[退出状态2](http://stackoverflow.com/a/40484670/699305)是Unix实用程序中不正确的命令行使用的通用标准,不仅仅是"某些版本的unix",而是一般的.本答案中显示的标题不反映实际惯例,现在或在1987年编写时. (6认同)
  • 请注意,在某些版本的unix中,某些命令使用退出状态2来指示其他内容.例如,grep的许多实现使用退出状态2来指示错误,并使用退出状态1表示没有找到选定的行. (5认同)
  • 在BSD上有一个总结sysexits.h信息的手册页:`man sysexits` (3认同)
  • ABS 并不“伟大”。请仔细阅读该主题;批评并不难。 (3认同)
  • @Schof,...Wooledge BashGuide 是专门编写的_因为_freenode 的 #bash 频道的居民厌倦了试图消除其他人从 ABS 学到的不良做法和完全错误的信息。(一些完全不准确的地方已经被清除,但今天仍然充斥着不良实践的例子,而且它的维护者完全不愿意捍卫或更新内容以回应批评)。 (2认同)

eph*_*ent 84

返回代码的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" */
}
Run Code Online (Sandbox Code Playgroud)

你是如何确定退出状态的?传统上,shell只存储一个8位返回码,但如果进程异常终止则设置高位.

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

如果你看到的不是这个,那么程序可能有一个SIGSEGV信号处理程序然后exit正常调用,所以它实际上并没有被信号杀死.(程序可以选择处理除SIGKILL和之外的任何信号SIGSTOP.)

  • 鉴于问题现在出现的方式,这似乎并不是最有用(也因此被接受)的答案. (8认同)

seg*_*ult 69

'1' >>>捕获一般错误

'2' >>>滥用shell内置(根据Bash文档)

'126' >>>调用的命令无法执行

'127' >>>"命令未找到"

'128' >>>退出的参数无效

'128 + n' >>>致命错误信号"n"

'130' >>>脚本由Control-C终止

'255' >>>退出状态超出范围

这是为了bash.但是,对于其他应用程序,有不同的退出代码.

  • 注意,'control-C yield 130'与信号n的'128 + n'一致; control-C生成SIGINT,即信号2. (6认同)
  • 根据[Advanced Bash-Scripting Guide](http://www.tldp.org/LDP/abs/html/exitcodes.html),这些是RESERVED退出代码.这意味着对于用户指定的退出参数_,应该避免使用这些值. (4认同)
  • 这似乎是在没有归属的情况下从ABS中抄袭的.(我们可以说,因为ABS包含不正确或至少具有误导性的信息.) (3认同)

ale*_*xis 48

没有旧答案正确描述退出状态2.与他们声称的情况相反,状态2是命令行实用程序在被错误调用时实际返回的内容.(是的,答案可能是九年之久,有数百个赞成,但仍然是错误的.)

这是正常终止的真实,长期退出状态约定,即不是通过信号:

  • 退出状态0:成功
  • 退出状态1:"失败",由程序定义
  • 退出状态2:命令行使用错误

例如,diff如果它比较的文件相同则返回0,如果它们不同则返回1.通过长期约定,unix程序在被错误调用时返回退出状态2(未知选项,错误数量的参数等) 例如diff -N,grep -Y或者diff a b c都将导致$?设置为2.这是以往的做法20世纪70年代的Unix早期.

接受的答案解释时,命令会发生什么信号终止.简而言之,由于未被捕获的信号而导致的终止导致退出状态128+[<signal number>.例如,通过SIGINT(信号2)终止导致退出状态130.

笔记

  1. 几个答案将退出状态2定义为"滥用bash builtins".仅当bash(或bash脚本)以状态2退出时才适用.请将其视为错误使用错误的特殊情况.

  2. 最流行的答案中sysexits.h提到,退出状态("命令行使用错误")定义为64.但这并不反映现实:我不知道任何常见的Unix实用程序在错误调用时返回64(欢迎示例).仔细阅读源代码可以发现这是理想的,而不是真实用法的反映:EX_USAGEsysexits.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. 
    
    Run Code Online (Sandbox Code Playgroud)

    换句话说,这些定义并不反映当时(1993年)的惯例,而是故意与之不相容.更可惜的是.

  • 这个答案意味着标准化程度比实际情况高得多。值 2 的含义没有适当的标准化,因此可以预见,实际操作会非常复杂。确实,许多工具因使用不当而返回 2,但“不当使用”的含义并没有明确定义,而且许多其他工具也不遵守此约定。 (3认同)
  • 如果程序捕获 SIGINT、清理并退出,则状态是对程序有意义的任何状态。例如,“more”将重置终端模式并以状态 0 退出(您可以尝试一下)。 (2认同)
  • @tripleee“工具”也没有明确定义!:-) 当然,任何人都可以编写命令行程序,并且它可以返回任何内容,但是比 Linux 更早存在的老式“Unix 命令行实用程序”,或者 GNU coreutils 的内容,相当不错。对此一致。如果您不这么认为,请列出该组中一些不以这种方式使用状态 2 的工具。另外,“不当使用”是您的术语(我同意这是一个模糊的术语);我写了“命令行使用错误”,这是非常具体的:不存在或不兼容的选项,错误数量的非选项参数等。 (2认同)

Chr*_*uin 24

没有标准的退出代码,除了0意味着成功.非零并不一定意味着失败.

stdlib.h确实定义EXIT_FAILURE为1和EXIT_SUCCESS0,但这就是它.

关于段错误的11很有意思,因为11是内核在发生段错误时用来终止进程的信号编号.在内核或shell中可能存在一些将其转换为退出代码的机制.


小智 20

sysexits.h有一个标准退出代码列表.它似乎可以追溯到至少1993年和一些像Postfix这样的大项目使用它,所以我想它是要走的路.

从OpenBSD手册页:

根据样式(9),在结束程序时,使用任意值调用exit(3)来指示失败条件并不是一个好习惯.相反,应该使用来自sysexits的预定义退出代码,因此进程的调用者可以在不查找源代码的情况下粗略估计失败类.


小智 8

对于第一近似,0是成功的,非零是失败,1是一般失败,并且大于1的任何是特定失败.除了虚假和测试的微不足道的例外,它们都是为了成功提供1,我发现还有一些其他的例外.

更现实地,0表示成功或可能失败,1表示一般失败或可能成功,2表示一般失败,如果1和0都用于成功,但也可能成功.

如果比较的文件相同则diff命令为0,如果它们不同则为1,如果二进制文件不同则为2.2也意味着失败.less命令为失败提供1,除非你没有提供参数,在这种情况下,尽管失败,它仍会退出0.

more命令和spell命令为失败提供1,除非失败是由于权限被拒绝,不存在的文件或尝试读取目录.在任何一种情况下,尽管失败,它们都会退出0.

然后expr命令为sucess提供1,除非输出是空字符串或零,在这种情况下,0是成功的.2和3都是失败的.

然后是成功或失败模糊的情况.当grep找不到模式时,它会退出1,但它会退出2以获得真正的失败(如权限被拒绝).当Klist找不到票时,Klist也退出1,虽然这不是故障,而是当grep找不到模式时,或者当你找到一个空目录时.

所以,不幸的是,即使在非常常用的可执行文件中,unix强大似乎也没有强制执行任何逻辑规则集.


Dea*_*vey 5

程序返回16位退出代码.如果程序被信号杀死,则高位字节包含所使用的信号,否则低位字节是程序员返回的退出状态.

如何将退出代码分配给状态变量$?然后是shell.Bash保持状态的低7位,然后使用128 +(信号nr)来指示信号.

程序的唯一"标准"约定是0表示成功,非零表示错误.使用的另一个约定是在出错时返回errno.