从 bash 手册中,$?
多变的:
$?
扩展到最近执行的前台管道的退出状态。
我想知道为什么 bash$?
在按Ctrl-C
或 时更新变量Ctrl-Z
:
$ echo $?
0
$ ^C
$ echo $?
130
$ sleep 10
^Z
[1]+ Stopped sleep 10
$ echo $?
148
答案1
当您Ctrl+C按命令行时,不会退出任何内容,但会出现SIGINT
( 的处理程序sigint_sighandler()
)无论如何将退出状态设置为 130 (128 + 2,正如 DopeGhoti 的答案所解释的):
if (interrupt_immediately)
{
interrupt_immediately = 0;
last_command_exit_value = 128 + sig;
throw_to_top_level ();
}
if (interrupt_state)
{
if (last_command_exit_value < 128)
last_command_exit_value = 128 + SIGINT;
print_newline = 1;
DELINTERRUPT;
}
当您按Ctrl+C杀死后台进程时,shell 会观察到该进程已终止,并将退出状态设置$?
为 128 加上信号编号。
当您按下Ctrl+Z暂停后台进程时,外壳程序会观察到该进程发生了某些情况:它尚未死亡,但通过相同的系统调用(wait
和朋友)报告该信息。同样,shell 将退出状态设置$?
为 128 加上信号编号,即 148 (SIGTSTP = 20)。
答案2
因为0
是正常退出状态的退出代码。
拦截中断或中断信号不是通常的退出状态,也不是挂起到后台。非零退出代码告诉您正在发生的情况,以便您可以在脚本触发的作业被终止或挂起时在脚本中做出相应的反应,而不是以常规方式以非错误状态退出。
交互式 shell 会话,当您按下 时^C,会抛出一个SIGINT
信号(信号 2),中止当前的交互式命令条目,这是命令条目(即命令提示符)所处的非正常状态。这会导致它返回状态130(128+2),并给你一个新的提示。
更多详细信息请参见http://tldp.org/LDP/abs/html/exitcodes.html#EXITCODESREF。
答案3
$?
该标准规定,接收到的信号的值是,> 128
但标准没有说明如何做到这一点。
Bourne Shell 设置$?
信号的情况,它使用128 + signal number
ksh93用途256 + signal number
请注意,只有 1、2、3、6、9、14 和 15 号信号是可移植的。
换句话说:SIGTSTP 和 SIGSTOP 使用不可移植的号码。
为此,Bourne Shell 最近推出了一种新的便携式系统,请参阅http://schillix.sourceforge.net/man/man1/bosh.1.html请参阅 ${.sh.termsig} 变量。