汇知百科
白蓝主题五 · 清爽阅读
首页  > 故障排查

开发中如何调试进程 使用技巧与常见问题解析

开发中如何调试进程

写代码时,程序跑不起来或者行为异常是常事。尤其当涉及多个进程并发执行时,问题更难捉摸。比如你启动了一个服务,发现它卡住了,CPU 占满但没输出,这时候就得上手段查一查到底哪个进程在作怪。

用 ps 查看进程状态

在 Linux 或 macOS 上,最基础的命令是 ps。比如想看看当前用户的所有进程,可以输入:

ps aux | grep your_process_name

这条命令能帮你快速定位目标进程的 PID(进程 ID),后续操作都靠它。

用 top 或 htop 实时监控

如果某个进程占用 CPU 特别高,打开 top 就能一眼看出。它会列出实时资源消耗排名。更友好的替代工具是 htop,支持鼠标操作和颜色高亮,安装后直接运行即可:

htop

在里面找到可疑进程,按 F9 可以发送信号终止,也可以记下 PID 准备深入分析。

用 strace 跟踪系统调用

有时候进程“卡住”是因为在等系统调用返回,比如读文件、网络请求或锁资源。这时候可以用 strace 挂到进程上:

strace -p <PID>

你会看到它正在执行哪些系统调用。如果最后一行停在 read(3, ...futex 上,基本就能判断是阻塞点。

用 gdb 附加到进程查看堆栈

对于 C/C++ 或 Go 编写的程序,gdb 是个利器。即使进程正在运行,也能临时挂上去看它在干什么:

gdb -p <PID>

进入交互界面后输入 bt(backtrace),就能看到当前所有线程的调用栈。如果是死循环或死锁,通常能一眼看出来。

Python 进程怎么查

如果你跑的是 Python 脚本,可以利用 faulthandler 模块,在程序启动时加上:

python -q -X faulthandler your_script.py

当进程收到 SIGUSR1 信号时,它会自动打印所有线程的回溯信息。也可以手动触发:

kill -USR1 <PID>

然后去日志里看输出,就能知道当时在执行哪段代码。

查看进程打开的文件和端口

有时问题是出在文件句柄没释放,或者端口被占用了。用 lsof 能查清楚:

lsof -p <PID>

你会看到这个进程打开了哪些文件、连接了哪些网络地址。比如发现它连着一个已经宕机的数据库,问题就找到了。

利用日志分级输出

很多问题其实在日志里早有征兆。开发阶段建议把日志级别设成 DEBUG,尤其是使用多进程框架如 multiprocessing 或 Celery 时。每个子进程打一句启动日志,能避免“默默退出”的尴尬。

比如在 Python 中:

import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug(f"[PID {os.getpid()}] Worker started")

这样一旦出问题,翻日志就能对应到具体进程。

用 pstree 看进程关系

有些服务由主进程派生多个子进程,单独看 PID 不容易理清结构。用 pstree 可以直观展示父子关系:

pstree -p | grep your_app

如果发现一堆僵尸进程挂在主进程下,那可能是子进程退出后没被正确回收。

临时加断点调试

在开发环境中,最直接的办法还是加断点。比如在 Python 里插入:

import pdb; pdb.set_trace()

程序运行到这里会暂停,你可以一步步查变量、调用栈。虽然土,但有效。注意上线前记得删掉这些临时代码。