前言
之前写了几篇关于调试运行中进程方法的文章,本文总结一下常用的几种调试方法。
Python: 通过预置后门(调试接口)的方式调试运行中的进程 Python: 获取并发程序的 traceback 信息(threading/gevent/asyncio) Python: 使用 faulthandler 模块获取运行中进程的 traceback 信息
需要修改代码的方法
print/logging
最常用的方法是查看程序运行日志。这种方法适合可以通过日志分析出问题的常见,也是诊断问题的首选方法。
这种方法需要预先在合适位置记录有用的日志信息,如果出问题时没有相关的日志信息的话,这种方法就会比较难以诊断问题。
预置调试后门(接口)
这种方法通过预先在程序里置入用于调试的后门(接口),方便在诊断问题时提供查看问题现场,甚至进入程序运行时环境的的手段。
常用的预置功能有:
- 提供一种方法可以获取当前程序的 stack traceback 信息
- 提供一种行可以获取当前程序运行时关键变量 / 状态
- 提供一种方法可以进入当前程序运行时,方便在程序运行时环境中执行调试代码
- 提供一种方法可以触发特定功能或者运行特定代码
无需修改代码的方法
ps/proc
通过 ps 可以查看指定进程的各种信息,通过查看 /proc// 目录下的系统文件也可以查看指定进程的各种信息。
比如:通过 ps 可以查看进程是否是僵尸进程、是否是孤儿进程,查看进程的启动时间、了解进程是否发生过重启等。 通过查看 /proc// 目录下的各种系统文件可以获取进程的环境变量信息、 stack 信息、内存信息等。
strace
通过 strace 程序可以查看程序正在调用的系统调用。可以用 strace 在系统调用层面查看程序正在进行的操作, 比如可以查看程序是否死锁、是否正在处理 socket 请求,正在处理文件等。
gdb-python
使用 gdb-python 可以通过在 gdb 中执行几个命令就可以查看程序正在执行的代码等信息。
不过,使用 gdb-python 需要预先安装包含调试符号的 debug 版本的 python 解释器,并使用该 debug 版本的 python 执行程序,算是一个比较大的限制。
纯 gdb
所谓的纯 gdb 方法就是只需要安装 gdb 就可以了,不需要安装带调试符号版本的 debug python 就可以调试 python 进程。
方法是使用 gdb 的 -eval-command [1] 参数对进程执行包含了调试代码的 gdb 命令,实现在进程运行时环境中执行调试代码的目的。
pystack [2] 和 pyrasite [3] 这两个调试工具就是利用的这种方法实现的无需修改代码即可调试进程的功能。
总结
本文总结了几种调试运行中进程的方法,每种方法都有一定的局限性,实际诊断问题的时候往往要综合几种方法最终才有可能发现真正的问题所在。