Python中如何获取发送SIGTERM信号的进程PID?

最近测试环境遇到个问题,用 Python 服务老是被 SIGTERM 信号终止了,已经基本排查了是服务自己把自己干掉了,所以想用 python signal 模块捕一下 SIGTERM 信号,但是还有找到能记录下 SIGTERM 信号来自哪个进程的方法,大家有没有做过类似的功能呀,求教。或者能另辟蹊径分析到 SIGTERM 来源的方法也欢迎赐教。 感谢。


Python中如何获取发送SIGTERM信号的进程PID?
12 回复

不能。不可能的。


在Python里,如果你想获取那个给你当前进程发送了SIGTERM信号的进程PID,标准库的signal模块能帮上忙。不过,它没法直接告诉你发送者的PID,因为SIGTERM这类信号通常不携带这个信息。

但是,你可以用signal.signal()设置一个信号处理器,当SIGTERM到来时,通过其他系统调用(比如os.getpid()获取自己的PID,或者用subprocessps命令组合去查)来间接推断。最常见的情况是父进程(比如shell或进程管理器)发送的SIGTERM,这时你可以用os.getppid()获取父进程的PID。

下面是一个简单的示例,演示如何捕获SIGTERM并打印可能的发送者信息:

import signal
import os
import sys
import time

def sigterm_handler(signum, frame):
    # 当收到SIGTERM时,打印当前进程PID和父进程PID
    print(f"\n进程 {os.getpid()} 收到了 SIGTERM 信号。")
    print(f"父进程PID (可能的发送者): {os.getppid()}")
    # 这里可以添加其他逻辑,比如清理资源
    sys.exit(0)

# 设置SIGTERM的信号处理器
signal.signal(signal.SIGTERM, sigterm_handler)

print(f"当前进程PID: {os.getpid()}")
print("运行中,等待信号... 按 Ctrl+C 可手动结束。")

# 保持程序运行,等待信号
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("\n收到 KeyboardInterrupt,退出。")

核心点:

  • signal.signal(signal.SIGTERM, sigterm_handler) 这行是关键,它把sigterm_handler函数注册为SIGTERM信号的处理函数。
  • 在处理器里,os.getppid() 返回父进程的PID。在大多数由shell或init系统发送SIGTERM的情况下,这个父进程PID就是发送者。
  • 如果信号来自系统其他部分(比如kill命令或进程管理器),这个PID可能不是直接的发送者,但通常是发送链条中的关键一环。

一句话总结:signal模块捕获SIGTERM,在处理器里通过os.getppid()获取父进程PID作为最可能的发送者。

我记得 signal 模块也是很简单地封装一下系统信号处理的回调而已。
你这样的情况啊,用 bpftrace 试试看看?

你有看内核日志吗, 说不定被内核杀的

遇到过类似问题,某 C 扩展出现了 SIGSEGV,日志里就能发现了

看错了,SIGTERM 应该还不一样,忽略上一条

好的,感谢

是的,signal 封得比较简易,我试一下你说的 bprtrace,感谢指教!

看过,没有线索😬

好的,感谢交流

如果是用的 python3.3 及以上版本的话,可以使用 signal.sigwaitinfo
返回结果中包含 siginfo_t 这个数据结构,其中有 si_pid,si_uid 字段,分别为信号发出的 pid 和 用户 id
我简单测试了一下,可以拿到 pid

回到顶部