Linux中有标准的退出状态码吗?

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

我看到分割错误经常导致退出状态为11,尽管我不知道这只是我工作的地方的惯例(像这样失败的应用程序都是内部的)还是一种标准。

Linux中进程有标准的退出码吗?

327948 次浏览

当Linux返回0时,意味着成功。其他都意味着失败。每个程序都有自己的退出码,所以要把它们都列出来实在是太长了……!

关于11错误代码,它确实是分段错误编号,主要意味着程序访问了一个没有分配的内存位置。

' 1 ':捕捉所有一般错误

' 2 ':误用shell内置程序(根据Bash文档)

“126”:调用的命令不能执行

“127”:“命令未找到”;

“128”:退出的无效参数

“128 + n”:致命错误信号"n"

“130”:以Ctrl + C结尾的脚本

“255”:退出状态超出范围

这是给巴斯的。但是,对于其他应用程序,有不同的退出代码。

除了0表示成功之外,没有标准的退出码。非零也不一定意味着失败。

头文件stdlib.h确实将EXIT_FAILURE定义为1,将EXIT_SUCCESS定义为0,但仅此而已。

段错误上的11很有趣,因为11是内核在发生分段错误时用来终止进程的信号数。在内核或shell中,可能存在某种机制将其转换为退出代码。

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

退出码是如何分配给状态变量$的?然后到壳层。Bash保留状态的低7位,然后使用128 +(信号nr)表示信号。

程序的唯一“标准”约定是成功为0,错误为非0。使用的另一个约定是在错误时返回errno。

头文件sysexits.h有一个标准退出码列表。它似乎至少可以追溯到1993年,一些像后缀这样的大项目使用它,所以我认为这是一种方式。

OpenBSD手册页:

根据style(9),在结束程序时,用任意值调用exit(3)来指示失败条件并不是一个好的实践。相反,应该使用来自sysexits的预定义退出码,以便进程的调用者可以获得关于故障类的粗略估计,而无需查找源代码。

返回代码的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("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" */
}

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

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

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

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

与往常一样,高级Bash脚本编写指南具有伟大的信息: (这个链接在另一个答案中,但指向一个非规范的URL。)

1:一般错误的Catchall
2:错误使用shell内置程序(根据Bash文档)
126:被调用的命令不能执行
127: "command not found"
. 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 */

粗略地说,0代表成功,非0代表失败,1代表一般失败,大于1代表特定失败。除了false和test这两个简单的例外,我还发现了其他一些例外。

更现实地说,0意味着成功或可能失败,1意味着一般的失败或可能成功,2意味着一般的失败,如果1和0都用来表示成功,但也可能是成功。

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

more .命令和拼写命令给出1表示失败,除非失败是由于权限被拒绝、文件不存在或试图读取目录。在任何这些情况下,尽管失败,它们仍然退出0。

然后expr命令给出1表示成功,除非输出为空字符串或0,在这种情况下,0表示成功。2和3是失败。

还有一些情况下,成功或失败是模棱两可的。当grep未能找到一个模式时,它退出1,但它退出2是一个真正的失败(如拒绝许可)。当klist没有找到一个票据时,它也会退出1,尽管这并不比grep没有找到一个模式或当你ls一个空目录时更失败。

因此,不幸的是,Unix 权力似乎没有强制任何逻辑规则集,即使是在非常常用的可执行文件上。

以前的答案都没有正确描述退出状态2。与他们声称的相反,状态2是您的命令行实用程序在不正确调用时实际返回的结果。(是的,一个答案可以是九年前的,有数百个赞,但仍然是错误的。)

下面是真正的,长期存在的正常终止的退出状态约定,即不是通过信号:

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

例如,diff如果比较的文件相同,则返回0,如果不同则返回1。根据长期以来的惯例,unix程序返回错误调用时退出状态2(未知选项,错误的参数数量,等等)。例如,diff -Ngrep -Ydiff a b c都将导致$?被设置为2。这是自20世纪70年代Unix早期以来的实践。

简单地说,由于未捕获信号而导致的终止导致退出状态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年)的普遍做法,而是有意与之不相容。