如果进程的退出状态为0,则认为该进程已在Linux中正确完成。
我已经看到,分段错误通常会导致退出状态为11,尽管我不知道这仅仅是我工作的惯例(失败的应用程序都是内部的)还是标准的。
Linux中是否有用于进程的标准退出代码?
如果进程的退出状态为0,则认为该进程已在Linux中正确完成。
我已经看到,分段错误通常会导致退出状态为11,尽管我不知道这仅仅是我工作的惯例(失败的应用程序都是内部的)还是标准的。
Linux中是否有用于进程的标准退出代码?
Answers:
从wait(2)
&co返回时,将8位返回码和8位终止信号编号混合为一个值。。
#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'出口42'; 回声$? 42 $ sh -c'kill -SEGV $$'; 回声$? 分段故障 139 $ expr 139-128 11
如果您看到的不是此内容,则程序可能有一个SIGSEGV
信号处理程序,该信号处理程序随后exit
会正常调用,因此实际上并没有被信号杀死。(程序可以选择处理SIGKILL
和以外的任何信号SIGSTOP
。)
与往常一样,《高级Bash脚本指南》提供了很多信息:(这是在另一个答案中链接的,但链接到非规范的URL。)
1: 针对一般错误的Catchall
2:滥用shell内置函数(根据Bash文档)
126: 调用的命令无法执行
127: “找不到命令”
128: 退出的参数无效
128 + n: 致命错误信号“ n”
255:退出状态超出范围(退出仅接受0-255范围内的整数args)
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 */
man sysexits
'1' >>> Catchall,用于一般错误
'2' >>>滥用shell内置函数(根据Bash文档)
'126' >>>调用的命令无法执行
'127' >>>“找不到命令”
'128' >>>无效的参数退出
'128 + n' >>>致命错误信号“ n”
'130' >>>脚本被Control-C终止
'255' >>>退出状态超出范围
这是为了bash。但是,对于其他应用程序,存在不同的退出代码。
较早的答案均未正确描述退出状态2。与他们声称的相反,状态2是您的命令行实用程序在不正确调用时实际返回的内容。(是的,答案可能是九岁,有数百次投票,但仍然是错误的。)
这是正常终止(即不是通过信号)的真实,长期存在的退出状态约定:
例如,diff
如果比较的文件相同,则返回0;如果不同,则返回1。根据长期的惯例,unix程序在错误调用(未知选项,错误的参数数量等)时会返回退出状态2, 例如diff -N
,grep -Y
或diff a b c
将全部$?
设置为2。 1970年代Unix的早期。
该接受的答案解释时,命令会发生什么信号终止。简而言之,由于未捕获的信号而终止会导致退出状态128+[<signal number>
。例如,以SIGINT
(信号2)终止会导致退出状态130。
有几个答案将退出状态2定义为“滥用bash内置函数”。这仅在bash(或bash脚本)以状态2退出时适用。将其视为不正确使用错误的特殊情况。
在最流行的回答中sysexits.h
提到的中,退出状态(“命令行使用错误”)被定义为64。但这并不反映现实:我不知道任何常见的Unix实用程序会在不正确的调用时返回64(欢迎使用示例) )。仔细阅读源代码可以发现这是理想的,而不是真实用法的反映:EX_USAGE
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年)的通用做法,但有意与此不符。更可惜。
more
将重置终端模式并以状态0退出(您可以尝试)。
除了0表示成功,没有标准的退出代码。非零也不一定意味着失败。
stdlib.h确实定义EXIT_FAILURE
为1和EXIT_SUCCESS
0,但是仅此而已。
segfault上的11很有趣,因为11是发生segfault时内核用于终止进程的信号编号。内核或外壳中可能存在某种机制,可以将其转换为退出代码。
sysexits.h包含标准退出代码的列表。它似乎至少可以追溯到1993年,并且一些大型项目(如Postfix)都在使用它,所以我想这是要走的路。
在OpenBSD手册页中:
根据style(9),在结束程序时,用任意值调用exit(3)来指示失败状态是一种不好的做法。相反,应该使用sysexits的预定义退出代码,这样,过程调用者可以在不查找源代码的情况下大致了解故障类别。
近似地,成功是0,非失败是失败,其中1是一般性失败,大于1的是特定失败。除了琐碎的false和test异常(都被设计为给成功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表示成功,非零表示错误。使用的另一种约定是在出错时返回errno。
标准的Unix退出代码由sysexits.h定义,如前所述。便携式库(例如Poco)使用相同的退出代码-以下是它们的列表:
http://pocoproject.org/docs/Poco.Util.Application.html#16218
信号11是SIGSEGV(段违规)信号,与返回码不同。该信号由内核响应于错误的页面访问而生成,这导致程序终止。信号列表可以在信号手册页中找到(运行“ man signal”)。
当Linux返回0时,表示成功。其他任何方法都意味着失败,每个程序都有其自己的退出代码,因此将它们全部列出会很长。
关于11个错误代码,它的确是分段错误号,主要是指程序访问了未分配的内存位置。