扭曲的服务器:猴子补丁文件

Twisted server: monkey-patch file

我 运行 Twisted (Python 2.7.x) 在 Alpine Linux 3.7 inside Docker.

我现在想使用 twisted.internet.inotify 模块,但加载失败。

它在 twisted.python._inotify 中触发了以下异常:

name = ctypes.util.find_library('c')
if not name:
    raise ImportError("Can't find C library.")
libc = ctypes.cdll.LoadLibrary(name)
initializeModule(libc)

问题是 Alpine Linux 3.x 有一个错误使得 ctypes.util.find_library('c') return None.

我已经将代码与 inotify module, which I've successfully used in Alpine before, and that one deals with the issue in the following way 进行了比较:

_FILEPATH = ctypes.util.find_library('c')
if _FILEPATH is None:
    _FILEPATH = 'libc.so.6'

instance = ctypes.cdll.LoadLibrary(_FILEPATH)

所以我尝试在解释器中调用 ctypes.util.find_library('libc.so.6'),调用成功。

我现在想做的是猴子补丁 twisted.python._inotify 以便它加载 libc.so.6 而不是 c,但我不知道我该怎么做,因为我根本无法加载模块。

我有一个选择,那就是在 docker build 期间 sed 源代码,或者甚至可能在服务器启动后立即在服务器内部访问,但这感觉就像是 hack。

我看到 Twisted 包含一个 MonkeyPatch 模块,但我不知道如何使用它,或者它是否适合这个任务。

我怎样才能以最干净的方式解决这个问题?


注意:服务器 运行 作为非 root,因此它没有对 /usr/lib/python2.7/site-packages/twisted/python/_inotify.py.

的写入权限

这意味着我要么必须在 Docker 文件中 sed 它,要么在服务器启动时在内存中打补丁,然后再加载模块(如果可能的话,我'我更喜欢那个)。

除此之外,我希望您为 Twisted 贡献一个补丁,以彻底解决这个问题,或者使其更容易从应用程序代码或操作级别解决。

也就是说,这里有一个 monkey-patch 应该适合你:

import ctypes.util
def fixed_find_library(name):
    if name == "c":
        result = original_find_library(name)
        if result is not None:
            return result
        else:
            return "libc.so.6"
    return original_find_library(name)
original_find_library = ctypes.util.find_library
ctypes.util.find_library = fixed_find_library

# The rest of your application code...

这只需将您提出的解决问题的问题的逻辑编纂成代码即可。只要此代码在 _inotify.py 被导入之前运行,那么当它被导入时,它最终将使用 "fixed" 版本而不是原始版本。

虽然 Jean-Paul 指出的猴子修补似乎是最好的解决方法,但这里有一种修改 Twisted 源代码的方法。

当使用PythonDockerAPI到运行容器时:

container = client.containers.run(...)
patch = 'sed -i.bak s/raise\ ImportError/name\ =\ \"libc.so.6\"\ #\ raise\ ImportError/g /usr/lib/python2.7/site-packages/twisted/python/_inotify.py'
print container.exec_run(patch, user='root')

或在容器内 bash 时:

sed -i.bak s/raise\ ImportError/name\ =\ \"libc.so.6\"\ #\ raise\ ImportError/g /usr/lib/python2.7/site-packages/twisted/python/_inotify.py