为什么 bash 设置 $?(退出状态)在 Ctrl-C 或 Ctrl-Z 上为非零?

Eug*_*ash 7 command-line bash signals background-process exit-status

从 bash 手册中,关于$?变量

$? 扩展到最近执行的前台管道的退出状态。

我想知道为什么 bash$?在按下Ctrl-C或时更新变量Ctrl-Z

$ echo $?
0
$ ^C
$ echo $?
130
$ sleep 10
^Z
[1]+  Stopped                 sleep 10
$ echo $?
148
Run Code Online (Sandbox Code Playgroud)

Dop*_*oti 7

因为0是正常退出状态的退出代码。

拦截中断或中断信号不是通常的退出状态,也不是暂停到后台。非零退出代码告诉您这是正在发生的事情,以便您可以在脚本中做出相应的反应,如果它触发的作业被终止或暂停,而不是按常规以非错误状态退出。

交互式 shell 会话,当您按下 时^C,它会抛出一个SIGINT信号(信号 2),中止当前的交互式命令条目,这是命令条目(即命令提示符)所处的非正常状态。这会导致它返回状态 130 (128+2),并给你一个新的提示。

更多细节可以在http://tldp.org/LDP/abs/html/exitcodes.html#EXITCODESREF找到。

  • 该评论 ^ 应该是答案的一部分。 (2认同)

mur*_*uru 6

当您按下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 ();
  }
Run Code Online (Sandbox Code Playgroud)

并在throw_to_top_level()

if (interrupt_state)
  {
    if (last_command_exit_value < 128)
    last_command_exit_value = 128 + SIGINT;
    print_newline = 1;
    DELINTERRUPT;
  }
Run Code Online (Sandbox Code Playgroud)

当您按下Ctrl+C杀死后台进程时,shell 会观察到该进程已死亡,并将退出状态设置$?为 128 加上信号编号。

当您按下Ctrl+Z暂停后台进程时,shell 会观察到该进程发生了一些事情:它没有死,但是信息是通过同一个系统调用(wait和朋友)报告的。在这里,shell 也将退出状态设置$?为 128 加上信号编号,即 148 (SIGTSTP = 20)。