【问题标题】:flask running in mod_wsgi cannot write to /tmp在 mod_wsgi 中运行的烧瓶无法写入 /tmp
【发布时间】:2015-04-25 17:59:01
【问题描述】:

Apache v2.4.12-2

Mod_wsgi v4.4.8-1

Python v3.4.2

python-flask v0.10.1-5

Arch linux - 内核 3.12.36

我正在使用 mod_wsgi 和 flask 来托管服务器。我可以使用以下简化代码和通用 .wsgi 脚本重现此问题:

MainServer.py:

import flask

app = flask.Flask(__name__)

@app.before_first_request
def initstuff():
    test_file = '/tmp/test'
    with open(test_file, 'w') as f:
        f.write('test')

@app.route('/', methods=['GET'])
def rootdir():
    return 'Hello world'

MainServer.wsgi:

from MainServer import app as application

预期:内容为“test”的文件写入 /tmp

实际结果:没有文件被写入。日志中没有报告错误

如果我运行相同的代码,而是指向我的用户有权写入的任何其他目录,它会按预期创建文件。 /tmp 是我遇到此问题的唯一目录。

如果我直接运行上面的代码并使用flask的内置服务器(app.run),它可以按预期在/tmp中创建文件,没有任何问题。

我已确保 mod_wsgi 服务器以与 app.run 脚本相同的用户身份运行,并且该用户能够写入 /tmp。

--编辑--

直接从命令行运行 httpd 不会导致此问题。将 httpd 作为 systemd 服务启动

【问题讨论】:

  • 您使用strace 了解发生了什么吗?
  • strace 是对树莓派的谋杀。也许我应该开始在我的桌面上进行测试... Ran strace -ooutput httpd。当服务器完成启动并且不包含对我尝试打开的文件的任何引用时,此操作终止。有没有更好的方法来跟踪 apache 中的应用程序?
  • 确保传递-f 标志以便通过分叉。
  • 谢谢,我对 strace 不是特别熟悉。根据输出,它写入文件成功,它做到了!所以我想我没有另一个失败条件。使用 systemctl 启动 httpd 会导致写入失败,而直接启动 httpd 不会。
  • 如果文件已经存在并且是由另一个用户创建的,那么运行 Apache 的用户可能无法写入它。因此可能是文件所有权问题。

标签: python flask mod-wsgi


【解决方案1】:

我认为与这个答案有关: https://unix.stackexchange.com/questions/167835/where-apaches-tmp-located

Apache 可能正在使用 private-tmp,这会导致 /tmp 被重定向到 /var/tmp/systemd-private--httpd.service-/

【讨论】:

  • 这当然是分辨率。对于我原来的问题来说太晚了,但迟到总比没有好:)
【解决方案2】:

尝试将app 记录器级别设置为DEBUG(并添加一个处理程序):

import logging
from logging.handlers import RotatingFileHandler
import flask

app = flask.Flask(__name__)

@app.before_first_request
def initstuff():
    test_file = '/tmp/test'
    with open(test_file, 'w') as f:
        f.write('test')

@app.route('/', methods=['GET'])
def rootdir():
    return 'Hello world'

if __name__ == '__main__':
    handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=1)
    handler.setLevel(logging.DEBUG)
    app.logger.addHandler(handler)
    app.run(host='0.0.0.0', port=8056, debug=True, use_reloader=False)

然后查看app.log 看看问题出在哪里。

【讨论】:

  • 我有一个日志设置,但对其进行了一些修改,使其更类似于您所拥有的。除了 HTTP GET 等之外,我没有收到任何错误或感兴趣的信息。
  • 你有没有试过只创建文件而不使用flask看看有没有错误:python -c 'open("/tmp/test", "w").write("FOO")'
  • 效果很好。就像从没有 mod_wsgi 的烧瓶中写入一样。例如,如果我运行以下命令,则文件创建正确:python3 MainServer.py。但是在 apache 中使用 wsgi 运行它时,尽管没有抛出错误,但没有创建文件。
  • 是的,它有权限,/var/log 只包含来自服务启动的请求和正常调试信息。
  • 您可以检查 /var/log/messages 或尝试 chmod 777 /tmp,如果在 chmod 之后有效,那么它必须是权限或 SELinux 问题。
最近更新 更多