gdb 调试正在运行的python进程,线程

16 篇文章 0 订阅
2 篇文章 0 订阅

调试

为什么调试? 程序卡了、慢了、挂了、都得调试!!!

环境:

CentOS release 6.4 (Final)  (使用cat /etc/issue进行查看

python: 2.7.12  (使用 python --version 查看

准备

对于Ubuntu:

sudo apt-get install gdb python2.7-dbg (注意更换版本号)

Fedora:

sudo yum install gdb python-debuginfo

centos:

sudo yum install yum-utils

然后重要的修改一个文件(只是对centos需要),

红色部分改为1

/etc/yum.repos.d/CentOS-Debuginfo.repo

[debug]
name=CentOS-6 - Debuginfo
baseurl=http://debuginfo.centos.org/6/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-Debug-6

enabled=1

然后安装

sudo debuginfo-install glibc

sudo yum install gdb python-debuginfo 完成


使用

查看进程号:

ps -ef | grep "key_words"  (第二列即为进程号pid, 记下来)

对于Ubuntu, Fedora

先使用gdb python  -p pid

正常情况下会加载一些 symbols 注意需要用到的确保加载,如果有其他提示信息,说某个包或者库没安装,可自行百度安装

到这,应该是可以使用py-list 或是py-bt 查看源码或者python程序的栈信息了,如果不能,可以试试往下继续看。或许是gdb的扩展没装


对于centos

需要用到python提供的gdb扩展:libpython, 它的位置在 python的源码包下Toos/gdb目录下:

例如:/home/kratos/download/Python-2.7.12/Tools/gdb/libpython.py

当然如果找不到,也可以直接查看python版本,然后去网上下载源码,找到对应的路径

找到了位置之后,将这个路径(/home/kratos/download/Python-2.7.12/Tools/gdb/)加入到系统的环境变量中去,也就是path. 当然也可以稍后加入

下面,使用python 提供的扩展工具:

gdb --python /path/to/libpython.py -p pid 

然后使用py-bt 查看是否可行

如果是安装的GUN的gdb,需要手动载入扩展脚本

(gdb) python

>import sys

>sys.path.insert(0, "path_to_libpython_directory")

>import libpython (一定要导入)

>end

(gdb) 如果没报错,表示导入成功,不然,直接去查看路径是否写对,是否import,或者版本是否正确,版本不正确信息不能完全解析出来

到这,应该就可以使用 py-bt 来查看python的进程栈了。


当然,还可以通过使用扩展脚本 .gdbinit来使用pystack查看。

具体方法:

下载文件内容并保存到当前用户下(也就是在哪个用户状态下使用gdb命令), 文件名为:.gdbinit

可以这样做: curl -o .gdbinit http://svn.python.org/projects/python/trunk/Misc/gdbinit

然后使用进入 gdb -p pid ,使用pystack 查看。

似乎还有些问题,可能会有一些其他信息,例如: No Symol "CO" in current context

这里有两种方式可以解决:1. 重新编译python, 加入参数:"CFLAGS=-g -fno-inline -fno-strict-aliasing"  (当然这种做法不适合已经正在运行着的问题程序,那么就有下面一种了)

2. 给刚才的就东西打个补丁

将文件中的 

if $pc > PyEval_EvalFrameEx && $pc < PyEval_EvalCodeEx

替换为:

if $pc > PyEval_EvalFrameEx && $pc < PyEval_EvalCodeEx && $fp != 0

注意只是在pystack 和pystackv处替换即可。

现在应该没问题了。!!!


还有另外一些查看运行着的进程中的栈信息的方法,例如自定义一些debug_handler, 然后在程序中监听用户发来的信号,根据信号类型,提供debug_handler, 将程序的栈信息打印出来等。例如:下面这段代码

import code, traceback, signal

def debug(sig, frame):
    """Interrupt running process, and provide a python prompt for
    interactive debugging."""
    d={'_frame':frame}         # Allow access to frame object.
    d.update(frame.f_globals)  # Unless shadowed by global
    d.update(frame.f_locals)

    i = code.InteractiveConsole(d)
    message  = "Signal received : entering python shell.\nTraceback:\n"
    message += ''.join(traceback.format_stack(frame))
    i.interact(message)

def listen():
    signal.signal(signal.SIGUSR1, debug)  # Register handler
os.kill(pid, signal.SIGUSR1)

这里是打印出了站的locals和globals信息,还有frame信息。

经过我的测试,对于正在阻塞或卡住的程序,系统接收不到相应的信号,即使发送了SIGNUSR1,也不能及时将相关信息获取,当然这里只是初步验证, 还需进一步详细验证。

当然关于调试,还可以使用pdb:

import pdb

在程序相应的位置,使用pdb.set_trace(),会打开一个调试的shell,在这里可以做一些事情。

但是不符合这里的情况,就暂不考虑。

其他,关于什么线程查看,线程切换等的信息啊,网上很多,不浪费时间,直接在gdb 里面使用help,根据相应提示都能看到

还有其他的吗???

嗯,还有就是相对于java的Btrace, jstack 。 嗯,python3中新添了faulthandler, 也就是和debug_handler类似。

最后,附上优秀链接

wiki.python.org上面关于gdb debug 的内容: https://wiki.python.org/moin/DebuggingWithGdb

stackoverflow 上面关于python stack trace 的讨论: https://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application

python3中关于debug模块的补充:https://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application

可以作为参考的:https://www.cnblogs.com/chris-cp/p/6007100.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值