15 ( SIGTERM
) 可以被应用程序捕获和处理,如果它选择这样做的话,但目前可能没有
9 ( SIGKILL
) 显然不能被任何应用程序捕获。
但是,通常操作系统设置退出状态的方式是可以识别终止进程的信号。通常只有 exit(3) 函数的状态参数的低 8 位 [以及 _exit(2) 系统调用] 被复制到status
wait(2) 返回给父进程(运行外部脚本的 shell)的值中在你的例子中)。因此,这会在值中留下sizeof(int)-1
字节空间status
供操作系统用于填充有关已终止进程的其他信息。通常,wait(2) 手册页将描述解释等待状态的方式,从而将有关进程终止的任何附加信息与进程传递给 _exit(2) 的状态分开,IFF 进程退出。
不幸的是,脚本是否可以使用这些额外信息取决于执行脚本的 shell 如何处理它。
首先查看 shell 的手册页,了解如何解释$?
.
如果 shell 将整个status
int
值逐字提供给脚本(在$?
变量中),则可以解析该值并确定程序退出的方式和原因。大多数 shell 似乎并没有完全做到这一点(出于各种原因,其中最重要的可能是标准合规性),但它们至少做得足够远,可以解决您的查询(并且必须是 POSIX兼容的)。
例如,我在 Mac OS X 上运行 AT&T 版本的 KSH。我的 ksh(1) 手册页说,如果程序正常运行终止,则退出状态为 0-255(其中的值大概是传递给_exit(2)) 和 256+signum 如果进程被信号终止(编号为“signum”)。我不知道在 Linux 上,但在 OS X 上,bash 给出的退出状态与 Ksh 不同(bash 使用第 8 位来表示信号,因此只允许 0-127 作为有效的退出值)。(在 POSIX 标准中,wait(2) 声称 _exit(2) 的 8 个低位可用,而 shell 将等待状态转换为$?
仅保留 7 位。去搞清楚!Ksh 的行为违反了 POSIX,但它更安全,因为严格兼容的 shell 可能无法区分将值 128-255 传递给 _exit(2) 和已被信号终止的进程。)
所以,无论如何,我开始一个cat
进程,然后我从终端发送它SIGQUIT
(通过按 ^)(我使用SIGQUIT
是因为没有简单的方法SIGTERM
从终端键盘发送):
22:01 [2389] $ cat
^\Quit(coredump)
ksh: exit code: 259
(我EXIT
定义了一个 shell 陷阱来打印 $? 如果它不为零,那么您也可以在上面看到它)
22:01 [2390] $ echo $?
259
(259 是一个整数值,表示 wait(2) 返回给 shell 的状态)
22:02 [2391] $ bc
obase=16
259
103
^D22:03 [2392] $
(看到 259 的十六进制值是 0x0103,注意 0x0100 是十进制的 256)
22:03 [2392] $ signo SIGQUIT
#define SIGQUIT 3 /* quit */
(我有一个名为的 shell 别名signo
,用于搜索标头以查找表示符号信号名称的数字。请参见此处,状态值中的 0x03 与 . 的数字相同SIGQUIT
。)
对 wait(2) 系统调用的进一步探索以及相关的宏<sys/wait.h>
将使我们能够更多地了解正在发生的事情。
在 C 中,解码等待状态的基本逻辑使用以下宏<sys/wait.h>
:
if (!WIFEXITED(status)) {
if (WIFSIGNALED(status)) {
termsig = WTERMSIG(status);
} else if (WIFSTOPPED(status)) {
stopsig = WSTOPSIG(status);
}
} else {
exit_value = WEXITSTATUS(status));
}
我希望这会有所帮助!