Shell 信号从哪里来

Shell 信号从哪里来,shell,unix,solaris,signals,Shell,Unix,Solaris,Signals,我在solaris服务器上运行了一个shell脚本,它是一个非常复杂的脚本,需要调用其他shell或perl脚本,整个执行过程需要花费很长的时间——几个小时 奇怪的是,它总是异常地存在。我使用“truss”命令记录shell进程的系统调用。它表明原因似乎是信号的到达#15 SIGTERM。但我不知道信号是从哪里来的?有什么方法可以检测来自哪个进程的信号 我的服务器信息: uname -a SunOS zsups379 5.10 Generic_144488-07 sun4u sparc SUNW

我在solaris服务器上运行了一个shell脚本,它是一个非常复杂的脚本,需要调用其他shell或perl脚本,整个执行过程需要花费很长的时间——几个小时

奇怪的是,它总是异常地存在。我使用“truss”命令记录shell进程的系统调用。它表明原因似乎是信号的到达#15 SIGTERM。但我不知道信号是从哪里来的?有什么方法可以检测来自哪个进程的信号

我的服务器信息:

uname -a
SunOS zsups379 5.10 Generic_144488-07 sun4u sparc SUNW,Sun-Fire-880
桁架切片输出(23528为主进程,25213为23528的子进程):

信号作为IPC(进程间通信)的一个问题是,无法确定信号来自何处。由于您可能在
truss
输出中没有看到
kill(0,SIGTERM)
,因此可以假设信号不是来自trussed进程。因此,它必须来自其他地方——或者(可能,但不太可能)系统本身,或者(更有可能)另一个过程

我的记忆力正在衰退,部分原因是我从未使用过这种机制

POSIX中有带有
SA_sigino
标志和中定义的
SIGINFO\u t
结构的系统调用

标题应将
siginfo\u t
类型定义为一种结构,该结构应至少包括以下构件:

int           si_signo  Signal number. 
int           si_code   Signal code. 
int           si_errno  If non-zero, an errno value associated with 
                        this signal, as described in <errno.h>. 
pid_t         si_pid    Sending process ID. 
uid_t         si_uid    Real user ID of sending process. 
void         *si_addr   Address of faulting instruction. 
int           si_status Exit value or signal. 
long          si_band   Band event for SIGPOLL. 
union sigval  si_value  Signal value.
int信号编号。
int si_代码信号代码。
int si_errno如果为非零,则为与
此信号,如中所述。
pid_t si_pid发送进程ID。
uid\t是发送进程的实际用户ID。
void*si_addr错误指令的地址。
int si_状态退出值或信号。
SIGPOLL的长si_波段活动。
union sigval SIU值信号值。
信号作为IPC(进程间通信)方法的一个问题是,无法找出信号的来源。由于您可能在
truss
输出中没有看到
kill(0,SIGTERM)
,因此可以假设信号不是来自trussed进程。因此,它必须来自其他地方——或者(可能,但不太可能)系统本身,或者(更有可能)另一个过程

我的记忆力正在衰退,部分原因是我从未使用过这种机制

POSIX中有带有
SA_sigino
标志和中定义的
SIGINFO\u t
结构的系统调用

标题应将
siginfo\u t
类型定义为一种结构,该结构应至少包括以下构件:

int           si_signo  Signal number. 
int           si_code   Signal code. 
int           si_errno  If non-zero, an errno value associated with 
                        this signal, as described in <errno.h>. 
pid_t         si_pid    Sending process ID. 
uid_t         si_uid    Real user ID of sending process. 
void         *si_addr   Address of faulting instruction. 
int           si_status Exit value or signal. 
long          si_band   Band event for SIGPOLL. 
union sigval  si_value  Signal value.
int信号编号。
int si_代码信号代码。
int si_errno如果为非零,则为与
此信号,如中所述。
pid_t si_pid发送进程ID。
uid\t是发送进程的实际用户ID。
void*si_addr错误指令的地址。
int si_状态退出值或信号。
SIGPOLL的长si_波段活动。
union sigval SIU值信号值。

通过使用类似于以下内容的dtrace脚本,您可以轻松跟踪发送到进程的所有信号:

proc:::signal-send
/ args[2] == 15 /
{
    printf("Process %d (%s) killing %d (%s)\n",
            pid, execname, args[1]->pr_pid, args[1]->pr_fname);
}

通过使用类似于以下内容的dtrace脚本,您可以轻松跟踪发送到进程的所有信号:

proc:::signal-send
/ args[2] == 15 /
{
    printf("Process %d (%s) killing %d (%s)\n",
            pid, execname, args[1]->pr_pid, args[1]->pr_fname);
}

是的,我也注意到了siginfo\u t类型。事实上,我可以编写一个信号处理程序来获取主进程中的siginfo_t,比如我的示例中的进程23528,信号来自它的子进程25213。但是,如果信号是逐层发出和传输的,例如,进程25213不是真正的信号发送者,它只是捕获由其他进程生成的信号。进程25213的源代码对我来说是不可更改的,因此我无法为其添加信号处理程序。所以就像那样,我不能将信号处理程序添加到每一层子进程中。如何获取原始发件人进程?是的,我还注意到了siginfo\u t类型。事实上,我可以编写一个信号处理程序来获取主进程中的siginfo_t,比如我的示例中的进程23528,信号来自它的子进程25213。但是,如果信号是逐层发出和传输的,例如,进程25213不是真正的信号发送者,它只是捕获由其他进程生成的信号。进程25213的源代码对我来说是不可更改的,因此我无法为其添加信号处理程序。所以就像那样,我不能将信号处理程序添加到每一层子进程中。如何获取原始发件人流程?谢谢。这对我来说是一个新的方向,因为我以前从未使用过dtrace。我将尝试一下。事实上,在Solaris系统上,您会发现
/usr/demo/dtrace/sig.d
是dtrace可以做的一个示例。请试一试。@FrankH:我建议的脚本(现在已经修复)针对的是用户1038919的信号,一旦发生,就会显示任何SIGTERM。演示之一是对所有信号进行聚合统计,这当然很有趣,但不适合启动调查。谢谢。这对我来说是一个新的方向,因为我以前从未使用过dtrace。我将尝试一下。事实上,在Solaris系统上,您会发现
/usr/demo/dtrace/sig.d
是dtrace可以做的一个示例。请试一试。@FrankH:我建议的脚本(现在已经修复)针对的是用户1038919的信号,一旦发生,就会显示任何SIGTERM。演示之一是对所有信号进行聚合统计,这当然很有趣,但不太适合启动调查。