跳转到主要内容

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.forkos.forkpy 进行 monkeypatch,则将其设置为 False

  • activate_on - 设置为 "USR1""USR2" 或其他信号名称,或设置为数字,以便在发送此信号时启动 Manhole 线程。如果不想线程一直处于活动状态,这很有用。

  • thread - 设置为 True 以启动始终开启的 ManholeThread。默认:True。如果使用 oneshot_onactivate_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

您实际连接到套接字时会发生什么

  1. 检查凭证(如果是同一用户或 root)

  2. sys.__std*__/sys.std* 被重定向到 UDS

  3. 每个线程的堆栈跟踪都写入到 UDS

  4. 启动 REPL,以便您可以玩弄进程

已知问题

  • 使用线程和文件句柄(而不是原始文件描述符) verbose_destination 可能会导致死锁。请参阅错误报告:PyPyPython 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

类似项目

变更日志

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_typesys.last_valuesys.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)

项目详情


下载文件

下载您平台上的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。

源分发

manhole-1.8.1.tar.gz (41.1 kB 查看散列)

上传时间

构建分发

manhole-1.8.1-py3-none-any.whl (16.3 kB 查看散列)

上传于 Python 3

由以下支持

AWSAWS云计算和安全赞助商DatadogDatadog监控FastlyFastlyCDNGoogleGoogle下载分析MicrosoftMicrosoftPSF赞助商PingdomPingdom监控SentrySentry错误日志StatusPageStatusPage状态页面