检测向进程发送哪些信号的最简单方法是什么?

检测向进程发送哪些信号的最简单方法是什么?

fish我正在尝试调试我的 shell(特别是)向后台进程发送信号的问题。我希望能够识别进程正在接收什么信号。

理想情况下,我想要一些可以执行以下操作的程序:

$ log_signals > signals.txt &

然后将接收到的信号写入输出。然而,我不认为任何这样的程序已经存在。

捕获传入信号并检查它们的最简单方法是什么,最好不需要编写自己的程序?

(我运行的是 OS X,而不是 Linux,所以如果可能的话,我更喜欢一个与平台无关的答案。)

答案1

自从史蒂芬将此信息发布为评论,但我发现此信息比任何现有答案更有用,我将评论重新发布为答案。

仅适用于 Linux:strace默认打印信号,因此您可以使用该-e标志来静默所有系统调用,以便信号更清晰:

strace -e 'trace=!all' cmd

就我而言,我试图找出哪个进程正在杀死我正在运行的守护进程,所以我得到的输出如下所示:

[hendrenj@underling02 ~]$ strace -p 171869 -e 'trace=!all'
Process 171869 attached
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=151513, si_uid=1000} ---
+++ killed by SIGTERM +++

在这里您可以看到我附加到 PID 171869,并且该进程由 PID 151513 的进程发送了 SIGTERM。

如需进一步参考,您可以查看这篇博文,它建议使用诸如auditd(我相信如果您使用的是使用 SELinux 的发行版的话,SELinux 附带的工具)或stap(System Tap)之类的工具(如果strace不够强大的话)。

答案2

我意识到您可以直接连接trap命令来检测任何信号,而不是有一些依赖性。下面的脚本在信号上设置了一些“陷阱”(当相关信号进入时执行一个函数),然后将信号作为退出代码输出。如果您愿意,可以将退出更改为控制台输出。

#!/bin/sh

trap cleanup_1 1 # SIGHUP
trap cleanup_2 2 # SIGINT
trap cleanup_3 3 # SIGQUIT
trap cleanup_6 6 # SIGABRT
trap cleanup_15 15 # SIGTERM

cleanup_1()
{
  exit 1
}

cleanup_2()
{
  exit 2
}

cleanup_3()
{
  exit 3
}

cleanup_6()
{
  exit 6
}

cleanup_15()
{
  exit 15
}

echo "Started"
cat

答案3

您可以使用gdb以下方法来执行此操作:

gdb --batch -ex 'handle all print' -ex 'handle all nostop' -ex 'handle all pass' -ex 'run' cat将在 GDB 下运行 cat 并打印所有信号,将它们传递给程序而不停止执行。

对后台程序执行此操作比较困难,因为 GDB 会尝试进入后台。您可能最好使用 启动它cat &,然后将调试器附加到另一个窗口中:gdb -ex 'handle all print' -ex 'handle all nostop' -ex 'handle all pass' -ex 'c' (pgrep cat)[1]。按q[ENTER]三下即可通过所有垃圾,然后您就可以观看cat跑步了。

答案4

strace -o logfile -e signal=all cmdline

相关内容