Are there any standard exit status codes in Linux?
在Linux中,如果进程的退出状态为0,则认为该进程已正确完成。
我已经看到分割错误通常会导致退出状态为11,但我不知道这是否只是我工作的约定(失败的应用程序都是内部的)或标准。
Linux中的进程是否有标准的退出代码?
第1部分:高级bash脚本指南
与往常一样,《高级bash脚本编写指南》提供了大量信息:(这在另一个答案中链接,但链接到一个非规范的URL。)
1: Catchall for general errors
2: Misuse of shell builtins (according to Bash documentation)
126: Command invoked cannot execute
127: "command not found"
128: Invalid argument to exit
128+n: Fatal error signal"n"
255: Exit status out of range (exit takes only integer args in the range 0 - 255)
第2部分:系统出口.h
absg引用了
Linux上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | $ 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 */ |
从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #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 ", 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 ", WTERMSIG(status)); /* prints:"second child died with 11" */ } |
您如何确定退出状态?传统上,shell只存储8位返回代码,但如果进程异常终止,则设置高位。
1 2 3 4 5 6 7 | $ sh -c 'exit 42'; echo $? 42 $ sh -c 'kill -SEGV $$'; echo $? Segmentation fault 139 $ expr 139 - 128 11 |
如果您看到的不是这个,那么程序可能有一个
'1'>>>一般错误的catchall
'2'>>>误用shell内置项(根据bash文档)
'126'>>>调用的命令无法执行
'127'>>>"找不到命令"
'128'>>>要退出的参数无效
'128+N'>>>致命错误信号"N"
'130'>>>由Control-C终止的脚本
'255'>>>退出状态超出范围
这是给巴什的。但是,对于其他应用程序,有不同的退出代码。
以前的回答都没有正确描述退出状态2。与它们所宣称的相反,状态2是命令行实用程序在不正确地调用时实际返回的内容。(是的,一个答案可能有9年的历史,有数百张赞成票,但仍然是错误的。)
以下是正常终止的真实、长期的退出状态约定,即不通过信号:
- 退出状态0:成功
- 退出状态1:"失败",由程序定义
- 退出状态2:命令行使用错误
例如,如果所比较的文件相同,则
接受的回答解释了当命令被信号终止时会发生什么。简而言之,由于未捕获信号而终止会导致出口状态
有几个答案将退出状态2定义为"bash内置的误用"。这仅在bash(或bash脚本)以状态2退出时适用。将其视为不正确使用错误的特殊情况。
在最常见的回答中提到的
1
2
3
4
5
6
7 * 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年)的惯例,而是有意与之不相容。更可惜的是。
除了0表示成功外,没有标准的退出代码。非零也不一定意味着失败。
stdlib.h确实将
segfault上的11很有趣,因为11是内核在segfault事件中用来终止进程的信号号。很可能在内核或shell中有某种机制将其转换为退出代码。
sysexits.h有一个标准退出代码列表。它至少可以追溯到1993年,一些大型项目如postfix使用它,所以我认为这是一个可行的方法。
从OpenBSD手册页:
According to style(9), it is not good practice to call exit(3) with arbi-
trary values to indicate a failure condition when ending a program. In-
stead, the pre-defined exit codes from sysexits should be used, so the
caller of the process can get a rough estimation about the failure class
without looking up the source code.
对于第一个近似值,0是成功的,非零是失败,1是一般的失败,任何大于1的都是特定的失败。除了"假"和"测试"这两个小的异常,这两个都是为成功而设计的,还有一些我发现的其他异常。
更现实地说,0表示成功或失败,1表示一般失败或成功,2表示一般失败,如果1和0都用于成功,但也可能是成功。
如果比较的文件相同,diff命令给出0;如果文件不同,则给出1;如果二进制文件不同,则给出2。2也意味着失败。less命令给出1表示失败,除非您未能提供参数,在这种情况下,尽管失败,它还是退出0。
more命令和spell命令给出1表示失败,除非失败是由于权限被拒绝、文件不存在或试图读取目录造成的。在任何这些情况下,尽管失败,它们还是退出0。
然后expr命令给出1表示成功,除非输出为空字符串或零,在这种情况下,0表示成功。2和3是故障。
有时成功或失败是模棱两可的。当grep找不到模式时,它退出1,但它退出2是因为真正的失败(如权限被拒绝)。当klist找不到一张罚单时,它也会退出1,尽管这实际上并不比grep找不到模式或者当你是一个空目录时更失败。
因此,不幸的是,Unix的强大功能似乎没有强制执行任何逻辑规则集,即使是在非常常用的可执行文件上。
程序返回一个16位的退出代码。如果用信号终止程序,那么高阶字节包含所用的信号,否则低阶字节是程序员返回的退出状态。
如何将该退出代码分配给状态变量$?然后到了外壳。bash保持较低的7位状态,然后使用128+(信号nr)指示信号。
程序的唯一"标准"约定是0表示成功,非0表示错误。使用的另一个约定是在出错时返回errno。
标准的Unix出口代码是由sysexits.h定义的,正如另一个海报所提到的。Poco等可移植库使用相同的退出代码-以下是它们的列表:
http://pocoproject.org/docs/poco.util.application.html 16218
信号11是SIGSEGV(段冲突)信号,与返回代码不同。这个信号是由内核响应错误的页面访问而生成的,这会导致程序终止。信号列表可以在信号手册页中找到(运行"man signal")。
当Linux返回0时,意味着成功。任何其他的都意味着失败,每个程序都有自己的退出代码,所以列出所有这些代码会花很长时间…!
关于11个错误代码,它实际上是分段错误号,主要意味着程序访问了一个未分配的内存位置。