一个命令的退出状态是由该命令实现的还是由执行该命令的shell进程实现的?

一个命令的退出状态是由该命令实现的还是由执行该命令的shell进程实现的?

来自 bash 手册

已执行命令的退出状态waitpid是系统调用或等效函数返回的值 。退出状态介于 0 到 255 之间,但如下所述,shell 可能会特别使用高于 125 的值。 shell 内置命令和复合命令的退出状态也限于此范围。在某些情况下,shell将使用特殊值来指示特定的故障模式。

  1. 什么决定了执行命令的退出状态,

    • 命令本身,即命令的实现是否确定退出状态,即确定已执行命令的退出状态是命令的固有属性,就像解析命令执行的命令行参数是固有的命令,或
    • 执行该命令的 shell 进程?上面提到的
      系统waitpid调用在我看来,执行命令的退出状态是由shell进程实现的,命令本身与它本身执行的退出状态无关。
  2. 在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,前一个命令的退出代码都可以通过 的值获取$?

相关内容