设置core dump 文件生成目录
https://blog.csdn.net/chengde6896383/article/details/83345684

使用 gdb 调试运行中的 Python 进程
https://mozillazg.com/2017/07/debug-running-python-process-with-gdb.html

步骤一:开启core dump文件生成

ulimit -c unlimited

步骤二:设置core dump文件位置

vi /etc/sysctl.conf

修改(添加)如下两个变量

kernel.core_pattern =/var/core/core_%e_%p

kernel.core_uses_pid= 0

这里是改为生成目录在/var/core/,%e代表程序名称,%p是进程ID

如果想直接生成在可执行文件相同目录,前面不要加任何目录,直接

kernel.core_pattern =core_%e_%p

步骤三:让修改生效

sysctl -p/etc/sysctl.conf

  • 测试环境¶
  • 准备工作¶
  • 生成 core file¶
  • 可用的 python 相关的命令¶
  • 当前执行位置的源码¶
  • 当前位置的调用栈¶
  • 查看变量的值¶
  • 查看上层调用方的信息¶
  • 调试多线程程序¶
    • 查看所有线程¶
    • 切换线程¶
    • 同时操作所有线程¶
  • 参考资料¶

假设一个服务器上运行了下面这样的 test.py 程序,我们怎样才能知道程序是否在正常运行,运行到哪一步了呢?

import timedef do(x):time.sleep(10)def main():for x in range(10000):do(x)if __name__ == '__main__':main()

这个程序既没有日志也没有 print 输出,通过查看日志文件/标准输出/标准错误是没有办法确认程序状况的。 一种可行的办法就是使用 gdb 来查看程序当前的运行状况。

测试环境

  • 系统: Ubuntu 16.04.1 LTS
  • Python: 2.7.12

准备工作

安装 gdb 和 python2.7-dbg:

$ sudo apt-get install gdb python2.7-dbg

设置 /proc/sys/kernel/yama/ptrace_scope:

$ echo 0 |sudo tee /proc/sys/kernel/yama/ptrace_scope

运行 test.py:

$ python test.py &
[1] 6489

通过 gdb python PID 来调试运行中的进程:

$ gdb python 6489
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
...
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from python...Reading symbols from /usr/lib/debug/.build-id/90/d1300febaeb0a626baa2540d19df2416cd3361.debug...done.
done.
...
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug//lib/i386-linux-gnu/ld-2.23.so...done.
done.
0xb778fc31 in __kernel_vsyscall ()
(gdb)

生成 core file

为了不影响运行中的进程,可以通过生成 core file 的方式来保存进程的当前信息:

(gdb) generate-core-file
warning: target file /proc/6489/cmdline contained unexpected null characters
Saved corefile core.6489
(gdb) quit
A debugging session is active.Inferior 1 [process 6489] will be detached.Quit anyway? (y or n) y

可以通过 gdb python core.PID 的方式来读取 core file:

$ gdb python core.6489
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
...
Type "apropos word" to search for commands related to "word"...
Reading symbols from python...Reading symbols from /usr/lib/debug/.build-id/90/d1300febaeb0a626baa2540d19df2416cd3361.debug...done.
done.warning: core file may not match specified executable file.
[New LWP 6489]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
Core was generated by `python'.
#0  0xb778fc31 in __kernel_vsyscall ()
(gdb)

可用的 python 相关的命令

可以通过输入 py 然后加 tab 键的方式来查看可用的命令:

(gdb) py
py-bt               py-down             py-locals           py-up               python-interactive
py-bt-full          py-list             py-print            python

可以通过 help cmd 查看各个命令的说明:

(gdb) help py-bt
Display the current python frame and all the frames within its call stack (if any)

当前执行位置的源码

(gdb) py-list1    # -*- coding: utf-8 -*-2    import time345    def do(x):>6        time.sleep(10)789    def main():10        for x in range(10000):11            do(x)
(gdb)

可以看到当前正在执行 time.sleep(10)

当前位置的调用栈

(gdb) py-bt
Traceback (most recent call first):<built-in function sleep>File "test.py", line 6, in dotime.sleep(10)File "test.py", line 11, in maindo(x)File "test.py", line 15, in <module>main()
(gdb)

可以看出来是 main() -> do(x) -> time.sleep(10)

查看变量的值

(gdb) py-list1    # -*- coding: utf-8 -*-2    import time345    def do(x):>6        time.sleep(10)789    def main():10        for x in range(10000):11            do(x)
(gdb) py-print x
local 'x' = 12
(gdb)
(gdb) py-locals
x = 12
(gdb)

查看上层调用方的信息

(gdb) py-up
#9 Frame 0xb74c0994, for file test.py, line 11, in main (x=12)do(x)
(gdb) py-list6        time.sleep(10)789    def main():10        for x in range(10000):>11            do(x)121314    if __name__ == '__main__':15        main()
(gdb) py-print x
local 'x' = 12
(gdb)

可以通过 py-down 回去:

(gdb) py-down
#6 Frame 0xb74926e4, for file test.py, line 6, in do (x=12)time.sleep(10)
(gdb) py-list1    # -*- coding: utf-8 -*-2    import time345    def do(x):>6        time.sleep(10)789    def main():10        for x in range(10000):11            do(x)
(gdb)

调试多线程程序

测试程序 test2.py:

# -*- coding: utf-8 -*-
from threading import Thread
import timedef do(x):x = x * 3time.sleep(x * 60)def main():threads = []for x in range(1, 3):t = Thread(target=do, args=(x,))t.start()for x in threads:x.join()if __name__ == '__main__':main()
$ python test2.py &
[2] 12281

查看所有线程

info threads

$ gdb python core.12281(gdb) info threadsId   Target Id         Frame
* 1    Thread 0xb74b9700 (LWP 11039) 0xb7711c31 in __kernel_vsyscall ()2    Thread 0xb73b8b40 (LWP 11040) 0xb7711c31 in __kernel_vsyscall ()3    Thread 0xb69ffb40 (LWP 11041) 0xb7711c31 in __kernel_vsyscall ()
(gdb)

可以看到这个程序当前有 3 个线程, 当前进入的是 1 号线程。

切换线程

thread ID

(gdb) thread 3
[Switching to thread 3 (Thread 0xb69ffb40 (LWP 11041))]
#0  0xb7711c31 in __kernel_vsyscall ()
(gdb) info threadsId   Target Id         Frame1    Thread 0xb74b9700 (LWP 11039) 0xb7711c31 in __kernel_vsyscall ()2    Thread 0xb73b8b40 (LWP 11040) 0xb7711c31 in __kernel_vsyscall ()
* 3    Thread 0xb69ffb40 (LWP 11041) 0xb7711c31 in __kernel_vsyscall ()
(gdb)

现在切换到了 3 号线程。

可以通过前面所说的 py- 命令来查看当前线程的其他信息:

[Current thread is 1 (Thread 0xb74b9700 (LWP 11039))]
(gdb) py-list335            waiter.acquire()336            self.__waiters.append(waiter)337            saved_state = self._release_save()338            try:    # restore state no matter what (e.g., KeyboardInterrupt)339                if timeout is None:
>340                    waiter.acquire()341                    if __debug__:342                        self._note("%s.wait(): got it", self)343                else:344                    # Balancing act:  We can't afford a pure busy loop, so we345                    # have to sleep; but if we sleep the whole timeout time,
(gdb) thread 2
[Switching to thread 2 (Thread 0xb73b8b40 (LWP 11040))]
#0  0xb7711c31 in __kernel_vsyscall ()
(gdb) py-list3    import time456    def do(x):7        x = x * 3>8        time.sleep(x * 60)91011    def main():12        threads = []13        for x in range(1, 3):
(gdb)

同时操作所有线程

thread apply all CMD 或 t a a CMD

(gdb) thread apply all py-listThread 3 (Thread 0xb69ffb40 (LWP 11041)):3    import time456    def do(x):7        x = x * 3>8        time.sleep(x * 60)91011    def main():12        threads = []13        for x in range(1, 3):Thread 2 (Thread 0xb73b8b40 (LWP 11040)):3    import time456    def do(x):7        x = x * 3>8        time.sleep(x * 60)91011    def main():12        threads = []13        for x in range(1, 3):---Type <return> to continue, or q <return> to quit---
Thread 1 (Thread 0xb74b9700 (LWP 11039)):335            waiter.acquire()336            self.__waiters.append(waiter)337            saved_state = self._release_save()338            try:    # restore state no matter what (e.g., KeyboardInterrupt)339                if timeout is None:
>340                    waiter.acquire()341                    if __debug__:342                        self._note("%s.wait(): got it", self)343                else:344                    # Balancing act:  We can't afford a pure busy loop, so we345                    # have to sleep; but if we sleep the whole timeout time,
(gdb)

常用的 gdb python 相关的操作就是这些, 同时也不要忘记原来的 gdb 命令都是可以使用的哦。

gdb 调试python 进程,包括core dump 调试相关推荐

  1. Core Dump调试

    环境 本文以笔者操作系统ubuntu14.04 LTS为例介绍core dump功能. 首先查看系统是否使能了core dump功能: $ ulimit -c 0 返回0表示没有使能,我们需要使能该功 ...

  2. 记一次PyQT5 core dump调试过程

    1. 首先设置系统允许生成core dump文件 步骤一:开启core dump文件生成 ulimit -c unlimited 步骤二:设置core dump文件位置 vi /etc/sysctl. ...

  3. linux core dump调试

    1 cmake gdb 调试, CMakeLists.txt 设置 方法1: SET(CMAKE_BUILD_TYPE "Debug")   SET(CMAKE_CXX_FLAGS ...

  4. Pycharm下运行调试Python项目时,当调试既需要给调试的程序传入命令行参数又需要程序在设置的断点处停下里查看变量时的解决方法

      今天在调试了一个复杂的Python项目,其中这个项目的调试需要事先从命令行读取参数,并且在调试期间需要再事先设置的断点处停下来.检查相关的变量.   问题是,在Pycharm的Terminal 输 ...

  5. 段错误调试神器 - Core Dump详解

    一.前言: 有的程序可以通过编译, 但在运行时会出现Segment fault(段错误). 这通常都是指针错误引起的. 但这不像编译错误一样会提示到文件某一行, 而是没有任何信息, 使得我们的调试变得 ...

  6. linux下调试core dump方式汇总,工作必备技能

    缘起 调试,是开发流程中一个非常重要的环节.每个程序员都应,具备调试代码的能力,尤其对于从事 Linux 下的开发的读者. 从事 linux 下后台开发,有时候会遇到程序突然崩溃的情况,也没有任何日志 ...

  7. linux core 永久生效,【调试】Core Dump是什么?Linux下如何正确永久开启?

    内容简介 [调试]Core Dump是什么?Linux下如何正确永久开启? Core Dump是什么?Linux下如何正确永久开启? Core Dump是什么? Core Dump乍听之下很抽象. 当 ...

  8. 使用gdb和core dump迅速定位段错误

    使用gdb和core dump迅速定位段错误 关键字:gdb.段错误.core dump 一.什么是core dump core:内存.核心的意思: dump:抛出,扔出: core dump:前提: ...

  9. VSCode 联合调试Python/C++

    VSCode 联合调试Python/C++ 测试环境 编写C++扩展 1. 编写C++实现:`myadd.cpp` 2. 编写要调用该扩展的Python脚本: `myscript.py` 3. 编写s ...

最新文章

  1. sqlplusw下登录sys账户
  2. instancesRespondToSelector与respondsToSelector的区别
  3. table的分页打印
  4. 设计模式 - 建造者模式(Builder Pattern)
  5. 前端小课堂 js:what is the function?
  6. .net core 使用redis 基于 StackExchange.Redis
  7. heartbeat+iscsi+mysql实现双机高可用
  8. 渗透测试入门12之渗透测试简介
  9. SpringMVC框架----SessionAttribute注解
  10. 用多itemtype的具有addHeaderView的recyclerview,还是scrollview?
  11. winr8文件服务器,技术讨论 | Windows全版本提权之Win10系列解析
  12. REGEXP使用经验
  13. 遍历目录中的所有文件和目录,并生成全路径
  14. pr如何处理音效_在pr中怎么让声音变的好听?pr怎么让说话的声音更好听?
  15. Dubbo本地存根是什么,Dubbo本地伪装又是什么?
  16. Miracast协议
  17. ios 做不倒翁动画效果
  18. Mac电脑 绑定阿里云企业邮箱
  19. Linux-Shell(六)
  20. 一个列子演示java中软引用的回收时机

热门文章

  1. 解决vue项目中的前端跨域问题
  2. stream().map()
  3. Golang特辑---简单谈谈我所认为的垃圾回收机制
  4. thinkphp发起网络请求
  5. Sandboxie 5.12
  6. 蓝桥杯单片机国赛模块儿总结
  7. android 大富翁,安卓玩大富翁2和大富翁3
  8. Java毕设项目家校通管理系统(java+VUE+Mybatis+Maven+Mysql)
  9. 12纳米做出了7纳米的性能,为国产芯片打破美国限制指明道路
  10. 星网宇达惯导插入Windows系统 无法识别usb串口的解决方法