WSGIDaemonProcess 不影响 python 站点

WSGIDaemonProcess does not affect python site

我想在一台 CentOS 服务器上管理多个 Django 应用程序,每个域一个,使用虚拟主机和 virtualenvs(每个应用程序都有自己的虚拟环境)。

我将在这里展示我的配置、生成的日志并解释我期望(但未能)看到的内容。

我正在使用 mod_wsgi 4.4 和软件集合 rh-python34 和 httpd24。

我的虚拟主机是这样配置的:

全局配置

Define RROOT "/opt/rh/httpd24/root"
Define RDOCROOT "/opt/rh/httpd24/root/var/www"

WSGIScriptAlias /wsgi "${RDOCROOT}/wsgi-bin"
WSGIProcessGroup localhost
<Directory "${RDOCROOT}/wsgi-bin">
        Order allow,deny
        Allow from all
</Directory>

通过上面的配置,我想处理通过IP访问的服务器,例如去 123.123.123.123:80/wsgi/ 应该 运行 RDOCROOT/wsgi-bin 中的脚本。它不起作用,实际上对IP地址的请求是由第一个虚拟主机处理的。但这是一个附带问题。

每个虚拟主机配置(DOMAIN.COM 更改,例如 example1.com、example2.com)

<VirtualHost *:80>
        ServerName DOMAIN.COM
        ServerAdmin webmaster@DOMAIN.COM
        DocumentRoot "${RDOCROOT}/DOMAIN.COM/html"
        ErrorLog "${RDOCROOT}/DOMAIN.COM/error.log"
        CustomLog "${RDOCROOT}/DOMAIN.COM/access.log" combined
        <Directory "${RDOCROOT}/DOMAIN.COM/html">
                Options FollowSymLinks
                AllowOverride All
                Require all granted
                <IfModule mod_headers.c>
                        Header set Access-Control-Allow-Origin "http://DOMAIN.COM"
                </IfModule>
        </Directory>
        ScriptAlias /cgi/ "${RDOCROOT}/DOMAIN.COM/cgi-bin/"
        <Directory "${RDOCROOT}/DOMAIN.COM/cgi-bin">
                AllowOverride None
                Options None
                Require all granted
                AddDefaultCharset utf-8
        </Directory>

        WSGIDaemonProcess DOMAIN.COM python-path=${RDOCROOT}/DOMAIN.COM/wsgi:${RDOCROOT}/DOMAIN.COM/django-venv/lib/python3.4/site-packages/
        WSGIProcessGroup DOMAIN.COM

        WSGIScriptAlias /wsgi/ "${RDOCROOT}/DOMAIN.COM/wsgi-bin/"
        <Directory "${RDOCROOT}/DOMAIN.COM/wsgi-bin">
                Require all granted
        </Directory>
</VirtualHost>

因此,虚拟主机应该在 DOMAIN.COM/ 中包含 html 页面,在 DOMAIN.COM/cgi/ 中包含 /cgi-bin/ 脚本,在 DOMAIN.COM/wsgi/ 中包含 /wsgi-bin/ 脚本=],它们都有效。

问题是虚拟环境无效:无法加载来自该虚拟环境的包。为了进行调试,我将日志级别设置为 info 并创建了一个无法打印站点包目录的测试脚本:

$ cat wsgi-bin/app.py    
import site
raise RuntimeError('Site {} {}'.format(site.getuserbase(), site.getsitepackages()))

当我访问 DOMAIN.COM/wsgi/app.py 时,error.log 包含以下内容(没有前缀、时间戳和 pids):

mod_wsgi (pid=20267): Attach interpreter ''.
mod_wsgi (pid=20267): Adding '(null)' to path.
mod_wsgi (pid=20267): Adding '/opt/rh/httpd24/root/var/www/DOMAIN.COM/django-venv/lib/python3.4/site-packages/' to path.
mod_wsgi (pid=20267): Create interpreter 'WWW.DOMAIN.COM:80|/wsgi/app.py'.
mod_wsgi (pid=20267): Adding '(null)' to path.
mod_wsgi (pid=20267): Adding '/opt/rh/httpd24/root/var/www/DOMAIN.COM/django-venv/lib/python3.4/site-packages/' to path.
[remote SOMEIP] mod_wsgi (pid=20267, process='WWW.DOMAIN.COM', application='WWW.DOMAIN.COM:80|/wsgi/app.py'): Loading WSGI script '/opt/rh/httpd24/root/var/www/DOMAIN.COM/wsgi-bin/app.py'.
[remote SOMEIP] mod_wsgi (pid=20267): Target WSGI script '/opt/rh/httpd24/root/var/www/DOMAIN.COM/wsgi-bin/app.py' cannot be loaded as Python module.
[remote SOMEIP] mod_wsgi (pid=20267): Exception occurred processing WSGI script '/opt/rh/httpd24/root/var/www/DOMAIN.COM/wsgi-bin/app.py'.
[remote SOMEIP] Traceback (most recent call last):
[remote SOMEIP]   File "/opt/rh/httpd24/root/var/www/DOMAIN.COM/wsgi-bin/app.py", line 5, in <module>
[remote SOMEIP]     raise RuntimeError('Site {} {}'.format(site.getuserbase(), site.getsitepackages()))
[remote SOMEIP] RuntimeError: Site /usr/share/httpd/.local ['/opt/rh/rh-python34/root/usr/lib64/python3.4/site-packages', '/opt/rh/rh-python34/root/usr/lib/python3.4/site-packages', '/opt/rh/rh-python34/root/usr/lib/site-python']

从日志的第三行来看,virtualenv 似乎已正确添加到站点,但从脚本生成的最后一行来看,似乎使用了系统范围的站点包。

目录正确,已仔细检查。

我哪里失败了?

WSGIPythonHome

对于 virtualenv 安装,您可能需要专门使用 WSGIPythonHome

WSGIPythonHome ${RDOCROOT}/DOMAIN.COM/django-venv/

配置 WSGIDaemonProcesspython-path

您可能需要更改您提供的路径:

WSGIDaemonProcess DOMAIN.COM python-path=${RDOCROOT}/DOMAIN.COM/wsgi:${RDOCROOT}/DOMAIN.COM/django-venv/lib/python3.4/site-packages/

只使用其中之一(另请参阅 mod_wsgi 4.4.15 的发行说明)

WSGIDaemonProcess DOMAIN.COM python-path=${RDOCROOT}/DOMAIN.COM/django-venv/lib/python3.4/site-packages/

正在为其他 python

重新编译

在某些情况下,除了 WSGIPythonHomepython-path 技巧之外,您可能还需要 recompile mod_wsgi for that particular python version

直接在 wsgi 应用程序中配置 site

作为最后的手段,您可以在 wsgi app.py:

中配置站点包
import site
site.addsitedir('/opt/rh/httpd24/root/var/www/DOMAIN.COM/django-venv/lib/python3.4/site-packages')

mod_wsgi WSGIPythonPath

的已知问题

来自release notes for mod_wsgi 4.4.15:

  1. When specifying multiple directories for the Python module search path using the WSGIPythonPath directive, or the python-path option to WSGIDaemonProcess, it was failing under Python 3 due to incorrect logging. It was therefore only possible to add a single directory.