Nat*_*man 300 linux error-handling exit-code
如果进程的退出状态为0,则认为该进程已在Linux中正确完成.
我已经看到分段错误经常导致退出状态为11,但我不知道这是否只是我工作的惯例(那些失败的应用程序都是内部的)或标准.
Linux中的进程是否有标准退出代码?
Sch*_*hof 327
与往常一样,Advanced Bash Scripting Guide提供了很多信息 :(这是在另一个答案中链接的,但是与非规范URL相关联.)
1: 一般错误的捕获
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 */
Run Code Online (Sandbox Code Playgroud)
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
.)
seg*_*ult 69
'1' >>>捕获一般错误
'2' >>>滥用shell内置(根据Bash文档)
'126' >>>调用的命令无法执行
'127' >>>"命令未找到"
'128' >>>退出的参数无效
'128 + n' >>>致命错误信号"n"
'130' >>>脚本由Control-C终止
'255' >>>退出状态超出范围
这是为了bash.但是,对于其他应用程序,有不同的退出代码.
ale*_*xis 48
没有旧答案正确描述退出状态2.与他们声称的情况相反,状态2是命令行实用程序在被错误调用时实际返回的内容.(是的,答案可能是九年之久,有数百个赞成,但仍然是错误的.)
这是正常终止的真实,长期退出状态约定,即不是通过信号:
例如,diff
如果它比较的文件相同则返回0,如果它们不同则返回1.通过长期约定,unix程序在被错误调用时返回退出状态2(未知选项,错误数量的参数等) 例如diff -N
,grep -Y
或者diff a b c
都将导致$?
设置为2.这是以往的做法20世纪70年代的Unix早期.
该接受的答案解释时,命令会发生什么信号终止.简而言之,由于未被捕获的信号而导致的终止导致退出状态128+[<signal number>
.例如,通过SIGINT
(信号2)终止导致退出状态130.
几个答案将退出状态2定义为"滥用bash builtins".仅当bash(或bash脚本)以状态2退出时才适用.请将其视为错误使用错误的特殊情况.
在最流行的答案中sysexits.h
提到,退出状态("命令行使用错误")定义为64.但这并不反映现实:我不知道任何常见的Unix实用程序在错误调用时返回64(欢迎示例).仔细阅读源代码可以发现这是理想的,而不是真实用法的反映:EX_USAGE
sysexits.h
Run Code Online (Sandbox Code Playgroud)* 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年)的惯例,而是故意与之不相容.更可惜的是.
Chr*_*uin 24
没有标准的退出代码,除了0意味着成功.非零并不一定意味着失败.
stdlib.h确实定义EXIT_FAILURE
为1和EXIT_SUCCESS
0,但这就是它.
关于段错误的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强大似乎也没有强制执行任何逻辑规则集.
程序返回16位退出代码.如果程序被信号杀死,则高位字节包含所使用的信号,否则低位字节是程序员返回的退出状态.
如何将退出代码分配给状态变量$?然后是shell.Bash保持状态的低7位,然后使用128 +(信号nr)来指示信号.
程序的唯一"标准"约定是0表示成功,非零表示错误.使用的另一个约定是在出错时返回errno.