Manhole是一个进程内服务,它可以接受Unix域套接字连接,并展示所有线程的堆栈跟踪和一个交互式提示。
项目描述
特性
使用Unix域套接字,只有root或相同有效用户可以连接。
可以在线程或信号处理程序中运行连接(请参阅oneshot_on选项)。
可以在信号处理程序中启动监听连接的线程(请参阅activate_on选项)
与fork的应用程序兼容,在fork之后重新安装Manhole线程 - 必须为此修改os.fork/os.forkpty。
与gevent和eventlet兼容,但有一些限制 - 您需要使用以下任一项
使用oneshot_on,或者
禁用线程monkeypatching(例如:gevent.monkey.patch_all(thread=False),eventlet.monkey_patch(thread=False))
注意:在eventlet中,您可能需要先设置hub,以防止循环导入问题
import eventlet eventlet.hubs.get_hub() # do this first eventlet.monkey_patch(thread=False)
线程与使用signalfd的应用程序兼容(将为Manhole线程屏蔽所有信号)。
选项
manhole.install(
verbose=True,
verbose_destination=2,
patch_fork=True,
activate_on=None,
oneshot_on=None,
sigmask=manhole.ALL_SIGNALS,
socket_path=None,
reinstall_delay=0.5,
locals=None,
strict=True,
)
verbose - 将其设置为 False 以禁用日志记录。
verbose_destination - 详细消息的输出目标。将其设置为文件描述符或句柄。默认为未缓存的 stderr(stderr 2 文件描述符)。
patch_fork - 如果您不想对 os.fork 和 os.forkpy 进行 monkeypatch,则将其设置为 False
activate_on - 设置为 "USR1"、"USR2" 或其他信号名称,或设置为数字,以便在发送此信号时启动 Manhole 线程。如果不想线程一直处于活动状态,这很有用。
thread - 设置为 True 以启动始终开启的 ManholeThread。默认:True。如果使用 oneshot_on 或 activate_on,则自动切换为 False。
oneshot_on - 设置为 "USR1"、"USR2" 或其他信号名称,或设置为数字,以便 Manhole 在信号处理程序中监听连接。如果不想使用线程,这很有用。
sigmask - 将信号掩码设置为给定的列表(使用 signalfd.sigprocmask)。如果无法导入 signalfd,则不执行任何操作。**注意**:这是为了防止 Manhole 线程**窃取**任何信号;通常这没问题,因为 Python 会强制所有信号处理都在主线程中运行,但 signalfd 不会。
socket_path - 使用特定的路径用于 Unix 域套接字(而不是 /tmp/manhole-<pid>)。这将禁用 patch_fork,因为子进程无法重用相同的路径。
reinstall_delay - 延迟 Unix 域套接字的创建 reinstall_delay 秒。这有助于解决在使用 fork+exec 模式时清理失败的问题。
locals - 添加到 manhole 交互式 shell locals 的名称。
daemon_connection - 连接线程是守护进程(在应用退出时死亡)。默认:False。
redirect_stderr - 将 stderr 的输出重定向到 manhole 控制台。默认:True。
strict - 如果为 True,则在尝试安装 manhole 两次时将引发 AlreadyInstalled 异常。默认:True。
环境变量安装
Manhole 可以通过 PYTHONMANHOLE 环境变量进行安装。
This
PYTHONMANHOLE='' python yourapp.py
等同于在 yourapp.py 中有此代码
import manhole manhole.install()
环境变量中的任何额外文本都将传递给 manhole.install()。例如
PYTHONMANHOLE='oneshot_on="USR2"' python yourapp.py
您实际连接到套接字时会发生什么
检查凭证(如果是同一用户或 root)
sys.__std*__/sys.std* 被重定向到 UDS
每个线程的堆栈跟踪都写入到 UDS
启动 REPL,以便您可以玩弄进程
已知问题
使用线程和文件句柄(而不是原始文件描述符) verbose_destination 可能会导致死锁。请参阅错误报告:PyPy 和 Python 3.4。
SIGTERM 和套接字清理
默认情况下,Python不会调用具有默认SIGTERM处理的atexit回调函数。这导致manhole留下散乱的套接字文件。如果这不符合要求,你应该安装自定义的SIGTERM处理程序,以便正确调用atexit。
示例
import signal
import sys
def handle_sigterm(signo, frame):
sys.exit(128 + signo) # this will raise SystemExit and cause atexit to be called
signal.signal(signal.SIGTERM, handle_sigterm)
使用Manhole与uWSGI
由于uWSGI覆盖了信号处理,因此Manhole的设置有点复杂。一种方法是使用“uWSGI信号”(不是POSIX信号),让工作进程检查一个文件以获取要打开Manhole的pid。
在您的WSGI应用程序文件中添加以下内容
from __future__ import print_function
import sys
import os
import manhole
stack_dump_file = '/tmp/manhole-pid'
uwsgi_signal_number = 17
try:
import uwsgi
if not os.path.exists(stack_dump_file):
open(stack_dump_file, 'w')
def open_manhole(dummy_signum):
with open(stack_dump_file, 'r') as fh:
pid = fh.read().strip()
if pid == str(os.getpid()):
inst = manhole.install(strict=False, thread=False)
inst.handle_oneshot(dummy_signum, dummy_signum)
uwsgi.register_signal(uwsgi_signal_number, 'workers', open_manhole)
uwsgi.add_file_monitor(uwsgi_signal_number, stack_dump_file)
print("Listening for stack mahole requests via %r" % (stack_dump_file,), file=sys.stderr)
except ImportError:
print("Not running under uwsgi; unable to configure manhole trigger", file=sys.stderr)
except IOError:
print("IOError creating manhole trigger %r" % (stack_dump_file,), file=sys.stderr)
# somewhere bellow you'd have something like
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
# or
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain'), ('Content-Length', '2')])
yield b'OK'
要打开Manhole,只需运行echo 1234 > /tmp/manhole-pid,然后运行manhole-cli 1234。
要求
- OS:
Linux, OS X
- 运行时:
Python 2.7, 3.4, 3.5, 3.6或PyPy
类似项目
Twisted的manhole - 它具有颜色和服务器端历史记录。
wsgi-shell - 创建一个线程。
pyrasite - 使用gdb注入代码。
pydbattach - 使用gdb注入代码。
pyringe - 使用gdb注入代码,更可靠,但依赖于不幸的dbg Python构建。
变更日志
1.8.1 (2024-07-24)
在Python 3.11上修复了缓冲问题。见66。
清理了一些打包/测试问题。
删除了更多的Python 2遗留代码。
修复了许可证元数据。见:68。
1.8.0 (2021-04-08)
简化了连接关闭代码。由Anton Ryzhov在62中贡献。
在manhole-cli中使连接关闭更优雅。由Anton Ryzhov在63中贡献。
1.7.0 (2021-03-22)
通过sys.last_type,sys.last_value,sys.last_traceback修复了内存泄漏。由Anton Ryzhov在59中贡献。
修复了大量双重关闭错误,并简化了流处理程序代码。由Anton Ryzhov在58中贡献。
在manhole-cli中放宽了pid参数解析,允许使用任何前缀的路径(不仅限于/tmp)。
1.6.0 (2019-01-19)
测试改进(将一些跳过更改为xfail,在Travis中添加了osx)。
修复了长期存在的Python 2.7错误,在该错误中,安装线程化的manhole后,sys.getfilesystemencoding()会损坏。见51。
停止支持Python 2.6,3.3和3.4。
修复了当使用socket.setdefaulttimeout()时的处理。由“honnix”在53中贡献。
修复了一些拼写错误。由Jesús Cea在43中贡献。
在manhole-cli中修复了处理,以便超时实际上是秒而不是毫秒。由Nir Soffer在45中贡献。
在manhole-cli中清理了无用的轮询选项。由Nir Soffer在46中贡献。
记录并实现了使用Eventlet与Manhole一起使用的方法。见49。
1.5.0 (2017-08-31)
为connection_handler选项添加了两个字符串别名。现在您可以方便地使用connection_handler="exec"。
改进了handle_connection_exec。现在它有一个干净的退出(exit())方式,并且正确地关闭了套接字。
1.4.0 (2017-08-29)
添加了 connection_handler 安装选项。默认值是 manhole.handle_connection_repl,并提供了备用选项 manhole.handle_connection_exec(非常简单:无输出重定向,无堆栈跟踪输出)。
从测试网格中删除了 Python 3.2。它可能仍然可用,但支持它非常麻烦(pip/pytest 不再支持它)。
在测试网格中添加了 Python 3.5 和 3.6。
修复了将管道传递给 manhole-cli 的问题。现在 echo foobar | manhole-cli 将等待 1 秒从 manhole 获取输出(您可以使用 --timeout 选项来自定义此设置)。
修复了与较新 PyPy 相关的问题(由 gevent/eventlet 套接字解包引起)。
1.3.0 (2015-09-03)
允许在没有线程或激活的情况下配置 Manhole(如果您想手动激活)。
添加了使用 uWSGi 与 Manhole 一起使用的示例和测试。
修复了在 Python 3 上 manhole-cli 中的错误处理(exc 变量不再泄漏)。
修复了在 Python 3 上使用 gevent/eventlet 应用程序的支持(现在它们支持 Python 3)。
允许在非 strict 模式下重新安装 manhole(先前的安装将被取消)。
1.2.0 (2015-07-06)
更改了 manhole-cli
如果套接字文件不存在,不会在终端中用错误信息进行垃圾邮件式发送。
允许发送任何信号(新的 --signal 参数)。
修复了 PID 参数的一些验证问题。
1.1.0 (2015-06-06)
添加了对通过 PYTHONMANHOLE 环境变量安装 manhole 的支持。
添加了 strict 安装选项。将其设置为 false 以避免获取 AlreadyInstalled 异常。
添加了一个 manhole-cli 脚本,该脚本模拟 socat readline unix-connect:/tmp/manhole-1234。
1.0.0 (2014-10-13)
添加了 socket_path 安装选项(由 Nir Soffer 贡献)。
添加了 reinstall_delay 安装选项。
添加了 locals 安装选项(由 Nir Soffer 贡献)。
添加了 redirect_stderr 安装选项(由 Nir Soffer 贡献)。
大量内部清理(由 Nir Soffer 贡献)。
0.6.2 (2014-04-28)
修复了 OS X 的回归问题。
0.6.1 (2014-04-28)
支持 OS X(由 Saulius Menkevičius 贡献)。
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。