Linux中有没有标准的退出状态码?
如果Linux的退出状态为0,则认为该进程已在Linux中正确完成。
我已经看到,分段错误通常会导致退出状态为11,但我不知道这是否仅仅是我工作的约定(那些失败的应用程序都是内部的)或标准。
Linux中是否有进程的标准退出码?
返回码的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" */ }
你如何确定退出状态? 传统上,shell只存储一个8位的返回代码,但是如果进程exception终止则设置高位。
$ sh -c'exit 42'; echo $? 42 $ sh -c'kill -SEGV $$'; echo $? 分段故障 139 $ expr 139 - 128 11
如果你看到除此之外的任何东西,那么程序可能有一个SIGSEGV
信号处理程序,然后正常调用exit
,所以它实际上并没有被信号杀死。 (程序可以select处理SIGKILL
和SIGSTOP
以外的任何信号。)
第1部分:高级Bash脚本指南
与往常一样, 高级Bash脚本指南有很好的信息 :(这是链接在另一个答案,但非规范的URL。)
1:一般错误的Catchall
2:滥用shell buildins(根据Bash文档)
126:调用的命令无法执行
127: “找不到命令”
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 (eg, 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一般错误的Catchall
2误用shell buildins(根据Bash文档)
调用的命令不能执行
127“命令未find”
128无效的参数退出
128 + n致命错误信号“n”
130脚本由Control-C终止
255退出状态超出范围
这是为了bash。 但是,对于其他应用程序,则有不同的退出代码。
sysexits.h有一个标准的退出代码列表。 似乎至less可以追溯到1993年,像Postfix这样的大型项目使用它,所以我想这是一条路。
从OpenBSD手册页:
根据式(9),在结束程序时,以任意值调用exit(3)来指示失败条件是不好的做法。 相反,应该使用来自sysexits的预定义的退出代码,因此进程的调用者可以在不查看源代码的情况下对失败类进行粗略估计。
没有标准的退出代码,除了0意味着成功。 非零并不一定意味着失败。
stdlib.h确实将EXIT_FAILURE
定义为1,将EXIT_SUCCESS
定义为0,但是就是这样。
segfault上的11是很有趣的,因为11是内核在出现段错误时用来杀死进程的信号数。 在内核或shell中可能有一些机制将其转换为退出代码。
以下是正常终止的真正的,长期的退出状态约定(不是通过信号):
- 退出状态0:成功
- 退出状态1:由程序定义的“失败”
- 退出状态2:命令行使用错误
例如,如果它比较的文件是相同的,则diff
返回0;如果不同,则返回1。 通过长期的约定,unix程序在调用不正确时会返回退出状态2(未知选项,错误的参数数量等) 。例如, diff -N
, grep -Y
或diff abc
都会导致$?
被设置为2.自从20世纪70年代Unix以来,这一直是一种习惯做法。
接受的答案解释了当命令被信号终止时会发生什么。 简而言之,由于未被捕获的信号而终止导致退出状态128+[<signal number>
。 例如,通过SIGINT
( 信号2 )终止导致退出状态130。
笔记
-
以前的答案都没有正确描述退出状态2,因此这个答案。 相反,他们声称,状态2是你的命令行实用程序实际返回时调用不当。 (是的,答案可以有数百个upvotes,仍然是错的。)
-
有几个答案将退出状态2定义为“滥用bash builtins”。 这仅在bash (或bash脚本)以状态2退出时适用。请考虑使用错误的特殊情况。
-
在最stream行的答案中提到的
sysexits.h
中,退出状态EX_USAGE
(“命令行使用错误”)被定义为64.但是这并不反映现实:我不知道任何常见的Unix实用程序在错误时返回64调用(欢迎例子)。 仔细阅读源代码可以发现,sysexits.h
是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 other exit statuses that random programs may * already return.
换句话说,这些定义并不反映当时(1993年)的普遍做法,而是有意与之不相容的。 更可惜。
对于第一个近似,0是成功的,非零是失败的,1是一般失败,大于1的任何一个是特定的失败。 除了假设和testing的微小例外,这两个例外都是为了获得成功而devise的,还有一些我发现的例外。
更现实地说,0意味着成功或者失败,1意味着一般的失败或者成功,2意味着一般的失败,如果1和0都用于成功,但也可能成功。
如果比较的文件是相同的,diff命令会给出0,如果不同则为1,如果二进制文件不同则为2。 2也意味着失败。 如果没有提供参数,那么less命令会给出1,否则在失败的情况下会退出0。
更多的命令和spell命令给出1失败,除非失败是权限被拒绝,不存在的文件,或尝试读取目录的结果。 在任何这些情况下,尽pipe失败,它们都会退出。
然后expr命令给出1成功,除非输出是空string或零,在这种情况下,0成功。 2和3是失败的。
那么成功或失败就是模糊的。 当grep找不到模式时,它退出1,但是它退出2,出现真正的失败(如权限被拒绝)。 当Klist找不到票时,Klist也会退出1,尽pipe当grep没有find一个模式,或者当你是一个空目录的时候,这并不是真正的失败。
所以,不幸的是,unix权力似乎并没有强制执行任何逻辑规则,甚至在非常常用的可执行文件上。
程序返回一个16位退出码。 如果程序被一个信号所杀,那么高位字节包含所使用的信号,否则低位字节就是程序员返回的退出状态。
如何退出代码分配给状态variables$? 然后到达壳。 Bash保持状态的低7位,然后使用128 +(信号nr)指示信号。
程序唯一的“标准”惯例是成功为0,错误为非零。 使用的另一个约定是错误返回errno。
当Linux返回0时,意味着成功。 其他任何意思都是失败的,每个程序都有自己的退出代码,所以将它们全部列出是相当长的。
关于11错误代码,这确实是分段错误编号,主要是指程序访问了未分配的内存位置。
标准Unix退出代码由sysexits.h定义,作为另一个海报提到。 像Poco这样的便携式库使用相同的退出代码 – 这里是它们的列表:
http://pocoproject.org/docs/Poco.Util.Application.html#16218
信号11是与返回码不同的SIGSEGV(段违例)信号。 这个信号是由内核产生的,用于响应页面访问不良而导致程序终止。 信号列表可以在信号手册页find(运行“man signal”)。