在最近的一个项目中,我想在生产使用状态下调试我的程序。生产环境非常复杂,所以我想在遇到问题时调试程序。
这就是我想要实现的:每当我想调试时,我都会向程序发送一个kill信号,希望pdb调试器会出现。它是这样的:
import pdb
import signal
import time
def handler(signal, frame):
pdb.set_trace()
signal.signal(signal.SIGTERM, handler)
a=1
while True:
a+=1
time.sleep(1)
但是,由于我必须使用nohup
运行程序,所有输出都将重定向到nohup.out,因此我无法与pdb交互。
有什么类似的吗?
答案 0 :(得分:2)
如果从终端运行程序,可以使用tty
命令注意
你所使用的tty设备,并将其传递给环境中的程序:
TTY=`tty` nohup ./myprog.py
然后在处理程序中再次打开tty并将stdin和stdout设置为文件:
import sys,os
def handler(signal, frame):
tty = os.getenv('TTY')
sys.stdin = sys.stdout = open(tty,"r+")
pdb.set_trace()
如果您从评论中删除当前tty中的程序,那么您 可以使用相同的python代码尝试类似的东西。这次用你的程序运行:
TTY=/tmp/link nohup ./myprog.py &
并关闭终端。打开一个新终端并创建这个新tty的缺失链接:
ln -s `tty` /tmp/link
然后在一行中给出kill命令以表示python进程,并且
然后立即做sleep
。这样shell就不再竞争了
pdb用于来自tty的输入。例如,在一行:
kill -term $pid; sleep 99999
然后你将pdb连接到/ tmp / link,这是你的tty。当您退出pdb时,键入 ctrl-c 会停止睡眠。
如果你需要在pdb中使用 ctrl-c ,并且你正在使用bash,
将sleep 99999
替换为suspend
。退出pdb时,使用终端的菜单发送信号sigcont
到了暂停bash的过程。
答案 1 :(得分:0)
我认为一种完全不同的方法是使用rpyc
,这种方法更简单,更优雅。我已经在我的复杂系统中使用这种方法很长一段时间了,它使得实时调试变得非常容易。
基本上,您需要做的是定义一个简单的rpyc API服务,其中包含" exposed"将引用(" netrefs")返回给系统中最有趣的对象的方法。然后,在启动时启动进程中的rpyc ThreadedServer。
然后,只要您愿意,您就可以创建一个rpyc客户端,并连接到该进程,通过API检索对对象的引用,并检查它们(透明地,就像那些netref是本地对象一样)。使用正确的API方法,您几乎可以在实时流程中访问所需的任何。
这个评价的其他优点是:(1)这个交互式会话甚至不会影响正在运行的过程(当然,除非你调用导致副作用的方法等),(2)它不必具有交互性,即您可以轻松编写连接到流程的脚本并从中打印一些信息。