Python: 通过预置后门的方式调试运行中的进程

比如输出当前程序的 traceback 信息,这样就可以知道当前程序运行到哪里了,甚至知道代码执行位置的局部变量和全局变量的值。

在下面的示例程序中,程序在接收到 USR1
信号时输出程序的 traceback 信息:

# -*- coding: utf-8 -*-
from queue import Queue
import signal
import sys
import threading
import time
import traceback


def output_tracebacks(signum, frame):
    id2thread = {}
    for thread in threading.enumerate():
        id2thread[thread.ident] = thread
    for thread_id, stack in sys._current_frames().items():
        stack_list = traceback.format_list(traceback.extract_stack(stack))
        print('thread {}:'.format(id2thread[thread_id]))
        print(''.join(stack_list))


def setup_backdoor():
    signal.signal(signal.SIGUSR1, output_tracebacks)


def worker(q):
    while True:
        task = q.get()
        if task is None:
            break
        # do something with task
        time.sleep(1.2)


def producer(q):
    for x in range(100):
        q.put(x)
        time.sleep(1)
    q.put(None)


setup_backdoor()
q = Queue()
t1 = threading.Thread(target=producer, args=(q,))
t1.start()
t2 = threading.Thread(target=worker, args=(q,))
t2.start()
for t in [t1, t2]:
    t.join()

运行程序并通过 USR1
信号激活后门,获取程序的 traceback 信息:

$ python testa.py &
[1] 79163
$ kill -s USR1 79163
thread :
  File "/xxx/lib/python3.6/threading.py", line 884, in _bootstrap
    self._bootstrap_inner()
  File "/xxx/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/xxx/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "testa.py", line 30, in worker
    time.sleep(1.2)

thread :
  File "/xxx/lib/python3.6/threading.py", line 884, in _bootstrap
    self._bootstrap_inner()
  File "/xxx/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/xxx/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "testa.py", line 36, in producer
    time.sleep(1)

thread :
  File "testa.py", line 47, in 
    t.join()
  File "/xxx/lib/python3.6/threading.py", line 1056, in join
    self._wait_for_tstate_lock()
  File "/xxx/lib/python3.6/threading.py", line 1072, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
  File "testa.py", line 15, in output_tracebacks
    stack_list = traceback.format_list(traceback.extract_stack(stack))

关于获取 traceback 信息的更多内容详见 Python: 获取并发程序的 traceback 信息(threading/gevent/asyncio)

稿源:Mozillazg's Blog (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 综合编程 » Python: 通过预置后门的方式调试运行中的进程

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录