Linux中是否有任何标准的退出状态代码?

时间:2009-07-09 05:24:04

标签: linux error-handling exit-code

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

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

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

10 个答案:

答案 0 :(得分:327)

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

与往常一样,Advanced Bash Scripting Guidegreat information:  (这是另一个答案,但与非规范网址相关联。)

  

1:导致一般错误的问题    2:滥用shell内置版(根据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 (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 :(得分:83)

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 'exit 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Segmentation fault
139
$ expr 139 - 128
11

如果你看到的不是这个,那么程序可能有一个SIGSEGV信号处理程序然后正常调用exit,所以它实际上并没有被信号杀死。 (除SIGKILLSIGSTOP之外,程序可以选择处理任何信号。)

答案 2 :(得分:70)

'1'&gt;&gt;&gt;笼罩一般错误

'2'&gt;&gt;&gt;滥用shell内置(根据Bash文档)

<强> '126'&GT;&GT;&GT;调用的命令无法执行

'127'&gt;&gt;&gt;“找不到命令”

<强> '128'&GT;&GT;&GT;退出

的参数无效

'128 + n'&gt;&gt;&gt;致命错误信号“n”

<强> '130'&GT;&GT;&GT;脚本由Control-C终止

'255'&gt;&gt;&gt;退出状态超出范围

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

答案 3 :(得分:47)

没有一个较旧的答案正确描述退出状态2。与他们声称的相反,状态2是您的命令行实用程序在被错误调用时实际返回的内容。(是的,答案可能是9年,有数百个upvotes,但仍然是错误的。)< / p>

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

  • 退出状态0:成功
  • 退出状态1:&#34;失败&#34;,由程序
  • 定义
  • 退出状态2:命令行使用错误

例如,如果它比较的文件相同,则diff返回0,如果它们不同则返回1。通过长期约定,unix程序在被错误调用时返回退出状态2(未知选项,错误数量的参数等)例如,diff -Ngrep -Y或{ {1}}都会导致diff a b c被设置为2.这是自20世纪70年代Unix早期以来的惯例。

accepted answer解释了当命令被信号终止时会发生什么。简而言之,由于未被捕获的信号导致的终止导致退出状态$?。例如,128+[<signal number>signal 2)终止会导致退出状态130.

备注

  1. 有几个答案将退出状态2定义为&#34;滥用bash builtins&#34;。仅当 bash (或bash脚本)以状态2退出时才适用。请考虑使用错误的特殊情况。

  2. sysexits.h中提到的most popular answer中,退出状态SIGINT(&#34;命令行使用错误&#34;)被定义为64.但是这并不反映现实:我不知道任何常见的Unix实用程序在错误调用时返回64(欢迎示例)。仔细阅读source code表明EX_USAGE是有抱负的,而不是真实用法的反映:

    sysexits.h

    换句话说,这些定义并不反映当时(1993年)的惯常做法,而是故意与之不相容。更多可惜。

答案 4 :(得分:23)

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

stdlib.h确实将EXIT_FAILURE定义为1,将EXIT_SUCCESS定义为0,但这就是它。

关于段错误的11很有意思,因为11是内核在发生段错误时用来杀死进程的信号编号。在内核或shell中可能存在一些机制,将其转换为退出代码。

答案 5 :(得分:20)

sysexits.h 有一个标准退出代码列表。它似乎可以追溯到至少1993年,一些像Postfix这样的大项目使用它,所以我想它是要走的路。

从OpenBSD手册页:

根据风格(9),用arbi-调用exit(3)是不好的做法。 trary值表示结束程序时的失败条件。在- 相反,应该使用来自sysexits的预定义退出代码,所以 该过程的调用者可以对失败类进行粗略估计 没有查找源代码。

答案 6 :(得分:8)

对于第一个近似值,0表示成功,非零表示失败,1表示一般故障,大于1表示特定故障。除了虚假和测试的微不足道的例外,这两个例外都是为了让成功1,我发现还有一些其他的例外。

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

如果比较的文件相同,则diff命令给出0,如果它们不同则为1,如果二进制文件不同则为2。 2也意味着失败。 less命令为失败提供1,除非你没有提供参数,在这种情况下,尽管失败,它仍会退出0。

more命令和spell命令为失败提供1,除非失败是由于权限被拒绝,不存在的文件或尝试读取目录。在任何一种情况下,尽管失败,它们都会退出。

然后expr命令为sucess提供1,除非输出是空字符串或零,在这种情况下,0是成功的。 2和3都是失败的。

然后有成功或失败模糊的情况。当grep找不到模式时,它会退出1,但它会退出2以获得真正的失败(如权限被拒绝)。当Klist找不到票时,Klist也会退出1,尽管这不是故障,而是当grep找不到模式时,或者当你找到一个空目录时。

所以,不幸的是,即使在非常常用的可执行文件中,unix也似乎没有强制执行任何逻辑规则集。

答案 7 :(得分:5)

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

如何将退出代码分配给状态变量$?然后是shell。 Bash保持状态的低7位,然后使用128 +(信号nr)来指示信号。

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

答案 8 :(得分:3)

标准Unix退出代码由sysexits.h定义,如另一张海报所述。 便携式库(如Poco)使用相同的退出代码 - 这是一个列表:

http://pocoproject.org/docs/Poco.Util.Application.html#16218

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

答案 9 :(得分:2)

当Linux返回0时,表示成功。其他任何东西都意味着失败,每个程序都有自己的退出代码,所以列出它们的时间很长......!

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