Linux 中退出代码的最小值和最大值是多少?

use*_*801 60 linux executable function exit-status

Linux 中以下退出代码的最小值和最大值是多少:

  1. 从二进制可执行文件(例如:C 程序)返回的退出代码。
  2. 从 bash 脚本返回的退出代码(调用 时exit)。
  3. 从函数返回的退出代码(调用时return)。我认为这是介于0和之间255

Sté*_*las 90

传递给_exit()/exit_group()系统调用的数字(有时称为退出代码,以避免退出状态的歧义,退出状态也指退出代码或信号编号的编码以及取决于进程是被终止还是正常退出的附加信息) 是类型int,所以在像 Linux 这样的类 Unix 系统上,通常是一个 32 位整数,其值从 -2147483648 (-2 31 ) 到 2147483647 (2 31 -1)。

但是,在所有系统上,当父进程(或子子收割者或父进程init死亡)使用wait(), waitpid(), wait3(),wait4()系统调用来检索它时,只有它的低 8 位可用(值 0 到 255 (2 8 - 1))。

当使用waitid()API(或 SIGCHLD 上的信号处理程序)时,在大多数系统上(正如 POSIX 现在在 2016 版标准中更明确地要求(参见_exit()规范)),完整的数字是可用的(在si_status返回结构的字段中) )。在 Linux 上情况并非如此,尽管它也会使用waitid()API将数字截断为 8 位,尽管将来可能会发生变化。

通常,您只想使用 0(通常表示成功)到 125 的值,因为许多 shell$?退出状态的表示中使用 128 以上的值来编码被杀死的进程的信号编号,而 126 和 127 用于特殊状况。

您可能希望使用 126 到 255exit()来表示与它们对 shell 所做的相同的事情$?(就像脚本那样ret=$?; ...; exit "$ret")。使用 0 -> 255 之外的值通常没有用。如果您知道父级将waitid()在不截断的系统上使用API,并且您碰巧需要 32 位范围的值,那么您通常只会这样做。请注意,如果您执行了一个exit(2048)示例,使用传统wait*()API 的父母将认为这是成功的。

更多信息请访问:

该问答应该有望回答您的大多数其他问题,并阐明退出状态的含义。我再补充几点:

一个进程不能终止,除非它被杀死或调用_exit()/exit_group()系统调用。当您从main()in返回时C,libc 会使用返回值调用该系统调用。

大多数语言都有一个exit()包装该系统调用的函数,并且它们所取的值(如果有的话)通常按原样传递给系统调用。(请注意,那些通常会做更多的事情,比如由 C 的exit()函数完成的清理工作,刷新 stdio 缓冲区,运行atexit()钩子......)

至少有以下情况:

$ strace -e exit_group awk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ strace -e exit_group mawk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ strace -e exit_group busybox awk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ echo | strace -e exit_group sed 'Q1234'
exit_group(1234)                        = ?
$ strace -e exit_group perl -e 'exit(1234)'
exit_group(1234)                        = ?
$ strace -e exit_group python -c 'exit(1234)'
exit_group(1234)                        = ?
$ strace -e exit_group expect -c 'exit 1234'
exit_group(1234)                        = ?
$ strace -e exit_group php -r 'exit(1234);'
exit_group(1234)                        = ?
$ strace -e exit_group zsh -c 'exit 1234'
exit_group(1234)
Run Code Online (Sandbox Code Playgroud)

当您使用 0-255 以外的值时,您偶尔会看到一些抱怨:

$ echo 'm4exit(1234)' | strace -e exit_group m4
m4:stdin:1: exit status out of range: `1234'
exit_group(1)                           = ?
Run Code Online (Sandbox Code Playgroud)

当您使用负值时,一些 shell 会抱怨:

$ strace -e exit_group dash -c 'exit -1234'
dash: 1: exit: Illegal number: -1234
exit_group(2)                           = ?
$ strace -e exit_group yash -c 'exit -- -1234'
exit: `-1234' is not a valid integer
exit_group(2)                           = ?
Run Code Online (Sandbox Code Playgroud)

如果传递给exit特殊内置函数的值在 0->255 之外,则 POSIX 会使行为未定义。

如果您这样做,某些 shell 会显示一些意外行为:

  • bashmksh但不是pdksh它所基于的)自行将值截断为 8 位:

    $ strace -e exit_group bash -c 'exit 1234'
    exit_group(210)                         = ?
    
    Run Code Online (Sandbox Code Playgroud)

    因此,在这些 shell 中,如果您确实想以 0-255 以外的值退出,则必须执行以下操作:

    exec zsh -c 'exit -- -12345'
    exec perl -e 'exit(-12345)'
    
    Run Code Online (Sandbox Code Playgroud)

    即在同一进程中执行另一个命令,该命令可以使用您想要的值调用系统调用。

  • 正如在其他问答中提到的那样,ksh93对于从 257 到 256+max_signal_number 的退出值,它具有最奇怪的行为,其中不是调用exit_group(),而是用相应的信号¹杀死自己。

    $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    zsh: suspended (signal)  ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    
    Run Code Online (Sandbox Code Playgroud)

    否则会截断数字,如bash/ mksh


¹ 不过这可能会在下一个版本中改变。现在开发ksh93已被接管为 AT&T 之外的社区工作,尽管 POSIX 以某种方式鼓励了这种行为,但正在恢复

  • 你知道是否有任何关于在 Linux 的 `si_status` 中实现完整退出代码的讨论吗? (2认同)
  • @Ruslan,不过是我提供的链接中的 http://austingroupbugs.net/view.php?id=594#c1318(来自 Eric Blake(RedHat)) (2认同)
  • 在兼容 POSIX 的操作系统上,您可以在最新版本的 Bourne Shell 中获得完整的 32 位退出代码,请参阅:http://schillix.sourceforge.net/man/man1/bosh.1.html (2认同)

小智 13

最小值为0,这被视为成功值。其他的都是失败。最大值255也称为-1

这些规则适用于脚本和其他可执行文件,以及 shell 函数。

更大的值导致模 256。

  • 准确地说,在一些类似 Bourne 的 shell(但不是 `bash` 或其他最常用的 shell)中,传递给 `exit` 内置函数的退出代码 *不* 被视为模 256,而是导致错误。(例如,常见的 `exit -1` 在大多数 shell 中实际上并不是等同于 `exit 255` 的便携式)。并且在 C 级别的 `exit(-1)` 是否等同于 `exit(255)` 是一个事实上肯定可以工作的细节,但依赖于实现定义的行为(尽管这在现代上不是问题)您可能在实践中使用的系统)。 (3认同)

Dam*_*mon 6

这看起来很简单,但哦,麻烦。

C 语言(以及直接或间接跟随大多数其他语言)要求返回 frommain等效于exit使用与返回值相同的参数进行调用。这是一个整数(返回类型很明确int),所以原则上范围是INT_MININT_MAX

但是,POSIX 声明只有最低 8 位传递给exit等待的父进程才可用,字面上就好像它是"status & 0xFF"
因此,实际上,退出代码是一个(仍然有符号的)整数,其中仅设置了最低 8 位。

因此最小值为 -128 ,最大值为 127。等等,这不是真的。它将是 0 到 255。

但唉,当然不可能这么简单。在实践中,Linux(或者更确切地说 bash)的做法不同。返回码的有效范围是 0 到 255(即无符号)。

为了避免混淆,为了安全起见,假设返回代码是未签名的,并将返回的任何内容转换为未签名可能是个好主意wait。这样它就与您在 shell 中看到的一致。由于最高位(包括最重要的位)被清除,这甚至不是“错误”,因为尽管技术上有符号,但实际值始终是无符号的(因为符号位从未设置)。
它还有助于避免将退出代码与 比较的常见错误-1由于某种奇怪的原因,即使程序退出时似乎也不会出现-1(好吧,猜猜为什么!)。

关于你的最后一点,从一个函数返回,如果这个函数恰好是main,那么见上文。否则,这取决于函数的返回类型是什么,原则上可以是任何类型(包括void)。