标识进程是否被bash中的信号杀死

问题描述 投票:-1回答:1

考虑这两个C程序:

#include <signal.h>

int main(void) {
    raise(SIGTERM);
}
int main(void) {
    return 143;
}

如果我运行任何一个,bash中$?的值将为143。The wait syscall可让您区分它们,但是:

wait

并且bash显然使用了这一知识,因为第一个导致wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGTERM}], 0, NULL) = 11148 wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 143}], 0, NULL) = 11214 被打印到终端上(奇怪的是,即使我将stdout和stderr都重定向到其他地方,也会发生这种情况),而第二个则没有。如何从bash脚本中区分这两种情况?

bash signals exit-code
1个回答
0
投票
我相信无法从纯bash / shell获取完整的退出代码。Terminated的答案非常全面。

所有shell之间的共同点是,如果进程正常终止,Unix' StackExchange包含退出代码的最低8位(传递给$?的数字)。

不同之处在于该过程由信号终止。在所有情况下,POSIX都需要该数字,该数字将大于128。POSIX没有指定该值是多少。但是实际上,在我所知道的所有类似Bourne的shell中,exit()的最低7位将包含信号编号。但是,$?是信号编号,

  • 在ash,zsh,pdksh,bash,Bourne shell中,n$?。这意味着在这些shell中,如果获得128 + n$?,则不知道是因为进程以129退出还是被信号exit(129)([C0 ](在大多数系统上)。但是基本原理是,当shell退出自身时,它们默认情况下会返回最后退出的命令的退出状态。通过确保1绝不大于255,可以使出口状态保持一致:

    HUP

出于这个原因,我认为您需要在bash之外运行命令以捕获退出代码。


[具有某种抽象性,关于$?有人问过$ bash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"' bash: line 1: 16720 Terminated sh -c "kill \$\$" 8f # 128 + 15 $ bash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?" bash: line 1: 16726 Terminated sh -c "kill \$\$" 8f # here that 0x8f is from a exit(143) done by bash. Though it's # not from a killed process, that does tell us that probably # something was killed by a SIGTERM ,这是用tcl编写的小脚本。更准确地说,

unbuffer将libexpect库与tcl / tk包装器一起使用。从unbuffer的源中,我提取了相关代码以得出解决方法。

similar question
如果unbuffer正常退出,则返回下一行:

#!/bin/bash expectStat() { expect <(cat << EOT set stty_init "-opost" set timeout -1 eval [list spawn -noecho ] $@ expect send_user "[wait]\n" EOT ) } expectStat sleep 5 & wait

如果睡眠在退出自身之前被杀死,则上面的脚本将返回:

sleep

如果脚本以18383 exp4 0 0
终止,则脚本将返回:

18383 exp4 0 0 CHILDKILLED SIGTERM {software termination signal}

这些字符串的含义可以从exit 143的手册中提取。集成功能18383 exp4 0 143
返回上面的返回行。

wait

通常返回四个整数的列表。第一个整数是等待的进程的pid。第二个整数是相应的生成ID。如果发生操作系统错误,则第三个整数为-1,否则为0。如果第三个整数为0,则第四个整数是生成的进程返回的状态。如果第三个整数为-1,则第四个整数是操作系统设置的errno值。还设置了全局变量errorCode。从等待返回值的末尾

可能会出现其他元素

。可选的第五个元素标识一类信息。当前,此元素唯一可能的值是CHILDKILLED,在这种情况下,接下来的两个值是C样式信号名称和简短的文本描述。
这意味着第四个值,如果存在,则六个值是您要查找的值。存储整行并提取信号和退出代码,例如,使用以下代码:

expect

最终,此解决方法非常小巧。也许还有另一个工具可以带来它自己的基于c的工具来获取信号的出现。
© www.soinside.com 2019 - 2024. All rights reserved.