centos7.6查看什么进程跑的流量_分析运行中的 Python 进程

7027b89461779ec0c97b5a38e3af41e4.png

在 Java 中打印当前线程的方法栈,可以用 kill -3 命令向 JVM 发送一个 OS 信号,JVM 捕捉以后会自动 dump 出来;当然,也可以直接使用 jstack 工具完成,这些方法好几年前我在这篇性能分析的文章 中介绍过。这样的需求可以说很常见,比如定位死锁,定位一个不工作的线程到底卡在哪里,或者定位为什么 CPU 居高不下等等问题。

现在工作中我用的是 Python,需要线上问题定位的缘故,也有了类似的需求——想要知道当前的 Python 进程“在干什么”。但是没有了 JVM 的加持,原有的命令或者工具都不再适用。传统的 gdb 的 debug 大法在线上也不好操作。于是我寻找了一些别的方法,来帮助定位问题,我把它们记录在这里。

signal

在代码中,我们可以使用 signal 为进程预先注册一个信号接收器,在进程接收到特定信号的时候,可以打印方法栈:

import traceback, signalclass Debugger(): def __init__(self, logger): self._logger = logger  def log_stack_trace(self, sig, frame): d={'_frame':frame} d.update(frame.f_globals) d.update(frame.f_locals)  messages = "Signal received. Stack trace:" messages += ''.join(traceback.format_stack(frame)) self._logger.warn(messages)  def listen(self): signal.signal(signal.SIGUSR1, self.log_stack_trace)

通过调用上面的 listen 方法(比如 new Debug(logger).listen()),就将一个可以接收 SIGUSR1 并打印方法栈的接收器注册到当前进程了。这里是打印方法栈,但是实际上可以做任何事,因为方法执行的当前,上下文已经跑到进程里面了。

那么怎么向进程发送信号呢?和 JVM 的方法类似,可以通过操作系统命令来发送:

kill -30 pid

这里的信号为什么是 30?这是因为 SIGUSR1 被当前操作系统定义成 30(请注意不同的操作系统这个映射表是可能不同的),这点可以通过 man signal 查看:

No Name Default Action Description1 SIGHUP terminate process terminal line hangup2 SIGINT terminate process interrupt program3 SIGQUIT create core image quit program4 SIGILL create core image illegal instruction5 SIGTRAP create core image trace trap6 SIGABRT create core image abort program (formerly SIGIOT)7 SIGEMT create core image emulate instruction executed8 SIGFPE create core image floating-point exception9 SIGKILL terminate process kill program10 SIGBUS create core image bus error11 SIGSEGV create core image segmentation violation12 SIGSYS create core image non-existent system call invoked13 SIGPIPE terminate process write on a pipe with no reader14 SIGALRM terminate process real-time timer expired15 SIGTERM terminate process software termination signal16 SIGURG discard signal urgent condition present on socket17 SIGSTOP stop process stop (cannot be caught or ignored)18 SIGTSTP stop process stop signal generated from keyboard19 SIGCONT discard signal continue after stop20 SIGCHLD discard signal child status has changed21 SIGTTIN stop process background read attempted from control terminal22 SIGTTOU stop process background write attempted to control terminal23 SIGIO discard signal I/O is possible on a descriptor (see fcntl(2))24 SIGXCPU terminate process cpu time limit exceeded (see setrlimit(2))25 SIGXFSZ terminate process file size limit exceeded (see setrlimit(2))26 SIGVTALRM terminate process virtual time alarm (see setitimer(2))27 SIGPROF terminate process profiling timer alarm (see setitimer(2))28 SIGWINCH discard signal Window size change29 SIGINFO discard signal status request from keyboard30 SIGUSR1 terminate process User defined signal 131 SIGUSR2 terminate process User defined signal 2

当然,也可以写一点点 python 脚本来发送这个信号:

import os, signalos.kill($PID, signal.SIGUSR1)

原理是一样的。

strace

如果进程已经无响应了,或者上面的信号接收器没有注册,那么就要考虑别的方法来或者“进程在干什么”这件事情了。其中,一个有用的命令是 strace:

strace -p pid

比如,我自己写了一个测试脚本 t.py,使用 python 执行,然后调用 sleep,再给它发送一个 SIGUSR1 的消息,它打印方法栈并退出。这整个过程,我使用 strace 可以得到这样的结果:

strace -p 9157strace: Process 9157 attachedselect(0, NULL, NULL, NULL, {9999943, 62231}) = ? ERESTARTNOHAND (To be restarted if no handler)--- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=9273, si_uid=9007} ---rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)stat("t.py
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值