来自 bash 手册
已执行命令的退出状态
waitpid
是系统调用或等效函数返回的值 。退出状态介于 0 到 255 之间,但如下所述,shell 可能会特别使用高于 125 的值。 shell 内置命令和复合命令的退出状态也限于此范围。在某些情况下,shell将使用特殊值来指示特定的故障模式。
什么决定了执行命令的退出状态,
- 命令本身,即命令的实现是否确定退出状态,即确定已执行命令的退出状态是命令的固有属性,就像解析命令执行的命令行参数是固有的命令,或
- 执行该命令的 shell 进程?上面提到的
系统waitpid
调用在我看来,执行命令的退出状态是由shell进程实现的,命令本身与它本身执行的退出状态无关。
在bash进程中,我们什么时候可以获得执行命令的退出状态,
- 仅当 bash 进程是交互式的,或者
- 不管 bash 进程是交互式的还是非交互式的?当 bash 进程是非交互式时,我们如何检索 bash 进程中执行的命令的退出状态?
答案1
命令本身可以通过exit()
系统调用的参数提供退出状态。 shell(或其他程序,Perl 或 PHP 中的怎么样?)可以通过或系统调用system()
获取子进程的退出状态。当子进程改变状态时,Unix/Linux/*BSD 内核都会安排向父进程传递 SIGCHLD。wait()
waitpid()
但还有其他情况。通过 SIGKILL 终止的进程没有机会退出。取消引用无效地址的进程将没有机会调用,exit()
除非安装了 SIGSEGV 信号处理程序。在这些情况下,内核会计算退出状态,其中包括一个表示“被信号杀死”的位,以及导致进程被杀死的信号。内核计算的退出状态被传递给被杀死进程的父进程。
答案2
该代码设置退出状态
$ perl -e 'END { $? = 42 }'; echo $?
42
$
除非它不
$ perl -e 'sleep 999; END { $? = 42 }'
^C
$ echo $?
130
$ echo $((130-128))
2
$ kill -l | head -2
1 HUP Hangup 17 STOP Stopped (signal)
2 INT Interrupt 18 TSTP Stopped
$
或确实
$ perl -e '$SIG{INT}=sub{exit 7};sleep 999'
^C$ echo $?
7
$
或者不应该让某人变得活泼SIGKILL
等等。
否则,bash
文档会产生误导,因为它waitpid
设置了 16 位状态字,但bash
仅在 shell 变量中传递该状态字的子集$?
。如果 shell 用户尝试将结果waitpid
视为 8 位值(事实并非如此),这可能会导致无知和混乱。
$ false; echo $?
1
$ perl -E 'system("false"); say $?'
256
$ perl -E 'system("false"); say $? >> 8'
1
$
答案3
进程确定其自己的退出代码。当它终止时,它提供退出代码,或者,如果没有提供,则假定为零(非错误)。
对于交互式和非交互式 shell,前一个命令的退出代码都可以通过 的值获取$?
。