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

我已经看到,分段错误通常会导致退出状态为11,尽管我不知道这是否是只是我工作的惯例(失败的应用程序全部是内部的)或标准。

Linux中是否有用于进程的标准退出代码?

评论

如果要查找系统功能返回的“系统错误号”,请查看errno

#1 楼

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" */
}
 


如何确定退出状态?传统上,外壳程序仅存储8位返回码,但是如果进程异常终止,则会设置高位。

这样,程序可能会有一个SIGSEGV信号处理程序,该信号处理程序随后会正常调用exit,因此它实际上并没有被信号杀死。 (程序可以选择处理SIGKILLSIGSTOP之外的任何信号。)

评论


考虑到问题出现的方式,这似乎不是最有用(因此也被接受)的答案。

– David J.
2013年12月9日在22:49



#2 楼

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

和往常一样,《高级Bash脚本指南》具有重要信息:
(这是另一个答案中的链接,但链接到非规范的URL。) />

1:常见错误的Catchall2:滥用shell内置函数(根据Bash文档)126:调用的命令无法执行127:“找不到命令” 128:退出参数无效128 + n:致命错误信号“ n” 255:退出状态超出范围(退出仅接受0-255范围内的整数args)


第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 */


评论


请注意,在某些类型的Unix中,某些命令使用退出状态2表示其他情况。例如,许多grep实现使用退出状态2表示错误,使用退出状态1表示未找到选定的行。

– NamshubWriter
2012年10月25日17:06

在BSD上,有一个手册页,汇总了sysexits.h中的信息:man sysexits

–georgebrock
13年7月29日在9:38

@NamshubWriter说了什么。退出状态2是在Unix实用程序中不正确使用命令行的通用方法,不仅是“某些类型的unix”,而且通常也是这样。此答案中显示的标题现在或1987年编写时均未反映实际约定。

–alexis
17年5月8日在9:16

ABS不是“伟大的”。请仔细阅读该主题;很难找到批评。

–tripleee
19年11月30日在9:05

但是sysexits.h的实际官方源代码在哪里?大家一直引用的手册页只是散文。例如,它引用EX_OK,但实际上并没有像其他代码那样以规范的方式定义它。还有更多缺少的东西吗?

– Garret Wilson
19年12月11日下午16:31

#3 楼

'1'>>>常见错误的所有内容

'2'>>>滥用shell内置函数(根据Bash文档)

'126'>>>调用了命令无法执行

'127'>>>“找不到命令”

'128'>>>退出参数无效

'128+ n'>>>致命错误信号“ n”

'130'>>>脚本被Control-C终止

'255'>>>退出状态超出范围

这是bash专用。但是,对于其他应用程序,存在不同的退出代码。

评论


看起来你们俩都在同一分钟内回答了。 Tian必须很快就能看到您的链接并将其粘贴。

–内森·费尔曼(Nathan Fellman)
2009年7月9日下午5:37

注意,“控制C的输出130”与信号n的“ 128 + n”一致; control-C生成信号2的SIGINT。

–乔纳森·莱弗勒(Jonathan Leffler)
2011年9月3日在18:44

这似乎是从ABS抄袭而来的,但没有注明出处。 (我们可以知道,因为ABS包含不正确或至少具有误导性的信息。)

–tripleee
16-10-10在8:43

根据高级Bash脚本指南,这些是保留的退出代码。因此,对于用户指定的退出参数,应避免使用这些值。

–在这里
17年1月9日在20:14

#4 楼

较早的答案均未正确描述退出状态2。与他们声称的相反,状态2是您的命令行实用程序在不正确调用时实际返回的内容。 (是的,答案可能是9岁,有数百次投票,但仍然是错误的。)

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


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

例如,如果diff比较的文件相同,则返回0,如果它们不同则返回1。按照长期的惯例,unix程序在错误调用(未知选项,错误的参数数量等)时会返回退出状态2,例如,diff -Ngrep -Ydiff a b c都将导致$?设置为2。

从1970年代Unix早期开始就采用这种做法。

公认的答案解释了当命令被信号终止时会发生什么。简而言之,由于未捕获的信号导致的终止导致退出状态128+[<signal number>。例如,通过SIGINT(信号2)终止会导致退出状态130。

注意事项


多个答案将退出状态2定义为“滥用bash内置函数”。这仅在bash(或bash脚本)以状态2退出时适用。将其视为错误使用错误的特殊情况。行使用错误“)定义为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年)的通用做法,但故意与之不符。更可惜。



评论


程序通过捕获SIGINT / Ctrl-C处理终止时应返回什么?还是130?除了bash之外,其他外壳的使用也很重要吗?

– Gringo Suave
18年7月20日在17:50

执行程序的外壳无关紧要;理论上,一个进程可以根据其父进程选择以不同的状态退出,但是我从未听说过发生这种情况的情况。

–alexis
18年7月24日在14:22



如果某个程序捕获了SIGINT,进行清理并退出,则该状态对于该程序有意义。例如,more将重置终端模式并以状态0退出(您可以尝试)。

–alexis
18年7月24日在14:23

这个答案意味着比实际情况高得多的标准化等级。值2的含义没有适当的标准化,因此可以预见的是实际的做法非常复杂。的确,许多工具针对不正确的使用会返回2,但是“不正确的使用”的含义还不是很明确,还有许多其他工具没有遵守该约定。

–tripleee
19年11月30日在9:02

@tripleee“工具”也没有很好的定义! :-)当然,任何人都可以编写命令行程序,并且可以返回任何内容,但是老式的“ Unix命令行实用程序”比Linux或GNU coreutils的内容要长得多对此保持一致。如果您有其他看法,请在此组中命名一些不使用状态2的工具。同样,“不当使用”是您的用语(我同意这是一个模糊的用语);我写了“命令行使用错误”,它非常具体:不存在或不兼容的选项,错误数量的非选项参数,等等。

–alexis
19/12/3在21:07



#5 楼

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

stdlib.h确实将EXIT_FAILURE定义为1并将EXIT_SUCCESS定义为0,但这就是关于它的内容。有趣的是,当出现段错误时,内核用来终止进程的信号号为11。内核或外壳中可能存在某种机制,可以将其转换为退出代码。

#6 楼

sysexits.h包含标准退出代码的列表。它似乎至少可以追溯到1993年,并且一些大型项目(如Postfix)都在使用它,所以我想这就是要走的路。 br />根据style(9),在结束程序时,用arbi-
trary值调用exit(3)指示失败情况不是一个好习惯。相反,应该使用sysexits的预定义退出代码,因此,该过程的调用者可以在不查找源代码的情况下大致了解故障类别



#7 楼

初步近似,成功为0,非零为失败,其中1为一般性失败,大于1的任何为特定失败。除了虚假和测试这两个平凡的异常(都旨在为成功赋予1)之外,我还发现了其他一些异常。

更现实地,0表示成功或失败,1表示一般失败或可能成功,如果1和0都用于成功,则2表示一般失败,但也可能成功。

如果比较的文件相同,则diff命令给出0,如果它们不同则给出1,如果二进制文件不同则给出2。 2也表示失败。 less命令为失败提供1,除非您不提供参数,否则即使失败也会退出0。

more命令和spell命令为失败提供1,除非失败是权限被拒绝,文件不存在或尝试读取目录的结果。在上述任何一种情况下,即使失败,它们也会退出0。 2和3都是失败。

然后在某些情况下,成功或失败是模棱两可的。当grep找不到模式时,它退出1,但是由于真正的失败(例如,权限被拒绝)而退出2。当找不到票证时,Klist也会退出1,尽管与grep找不到模式或当您创建一个空目录时相比,这实际上并不是更多的失败。 ,不幸的是,即使在非常常用的可执行文件上,unix的功能似乎也不强制执行任何逻辑规则。

评论


我也要指出diff的行为。 wget也有详细的错误(例如6个身份验证失败),但随后它们使用1 =通用错误,2..n =特定错误

–PypeBros
16年8月30日在10:25

#8 楼

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

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

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

#9 楼

标准的Unix退出代码由sysexits.h定义,正如另一个提及的内容。
便携式库(例如Poco)使用相同的退出代码-这是它们的列表: //pocoproject.org/docs/Poco.Util.Application.html#16218

信号11是SIGSEGV(段违规)信号,与返回码不同。该信号由内核响应于错误的页面访问而生成,这导致程序终止。信号列表可以在信号手册页中找到(运行“ man signal”)。

#10 楼

当Linux返回0时,表示成功。别的意思就是失败,每个程序都有自己的退出代码,因此将它们全部列出会很长...!

关于11个错误代码,它的确是分段错误号,主要是指程序访问了未分配的内存位置。

评论


它始终为11,因为内核会杀死它并分配“退出值”。同样,其他类型的故障将始终获得相同的退出值。

– Alex Gartrell
09年7月9日在6:04