Tim*_*Tim 3 bash command exit-status
来自 bash 手册
执行命令的退出状态是
waitpid
系统调用或等效函数返回的值 。退出状态介于 0 和 255 之间,但如下所述,shell 可能会特别使用 125 以上的值。shell 内置命令和复合命令的退出状态也仅限于此范围。在某些情况下,外壳会使用特殊值来指示特定的故障模式。
什么决定了执行命令的退出状态,
waitpid
系统调用在我看来是一个执行命令的退出状态是由shell进程实现的,而命令本身与一个执行本身的退出状态无关。在bash进程中,我们什么时候可以获取执行命令的退出状态,
命令本身可以通过exit()
系统调用的参数提供退出状态。shell(或其他程序,system()
在 Perl 或 PHP 中如何?)可以通过wait()
或waitpid()
系统调用获取子进程的退出状态。Unix/Linux/*BSD 内核都安排在子进程更改状态时将 SIGCHLD 传递给父进程。
但还有其他情况。通过 SIGKILL 终止的进程没有机会退出。exit()
除非安装了 SIGSEGV 信号处理程序,否则取消引用无效地址的进程将没有机会调用。在这些情况下,内核会计算一个退出状态,其中包含一个表示“被信号杀死”的位,以及是什么信号导致进程被杀死。内核计算的退出状态被传递到被杀死进程的父进程。
代码设置退出状态
$ perl -e 'END { $? = 42 }'; echo $?
42
$
Run Code Online (Sandbox Code Playgroud)
除非它不
$ 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
$
Run Code Online (Sandbox Code Playgroud)
或者做
$ perl -e '$SIG{INT}=sub{exit 7};sleep 999'
^C$ echo $?
7
$
Run Code Online (Sandbox Code Playgroud)
或者不应该有人变得活泼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
$
Run Code Online (Sandbox Code Playgroud)