对于 Apache 中嵌入的 Python,为什么 sys.path 在启动期间的初始化与从 bash 运行时的初始化不同
我使用 modwsgi 在 Apache 中嵌入 Python,我发现当 Apache 从 rc2.d 启动文件夹启动时,与从 shell 运行时相比,sys.path 没有正确初始化。
版本:
Ubuntu Lucid 10.04
阿帕奇2.2
Python 2.6
mod_wsgi 3.3
首先,我正在使用这个应用程序测试初始化:
import sys
import os
def application(environ, start_response):
status = '200 OK'
output = ['version %s\n'%sys.version]
output.append('sys.prefix = %s \n' % repr(sys.prefix))
output.append('sys.exec_prefix = %s \n' % repr(sys.exec_prefix))
output.append('sys.path = %s \n' % repr(sys.path))
output.append('env.PYTHONHOME = %s\n' % repr(os.environ.get('PYTHONHOME')))
output.append('env.PATH = %s\n' % repr(os.environ.get('PATH')))
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(sum([len(o) for o in output])))]
start_response(status, response_headers)
return output
当 apache2 通过 'sudo apache2ctl start' 或 'sudo /etc/init.d/apache2 start' 从 bash 启动时,它会正确初始化,上面的应用程序显示:
version 2.6.5 (r265:79063, Apr 16 2010, 14:15:55)
[GCC 4.4.3]
sys.prefix = '/usr'
sys.exec_prefix = '/usr/local'
sys.path = ['/usr/local/lib/python2.6/dist-packages/WebOb-1.0.7-py2.6.egg', '/usr/local/lib/python2.6/dist-packages/twiddler-0.9.1-py2.6.egg', '/usr/local/lib/python2.6/dist-packages/elementtree-1.2.7_20070827_preview-py2.6.egg', '/usr/local/lib/python2.6/dist-packages/lxml-2.3-py2.6-linux-x86_64.egg', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/local/lib/python2.6/lib-dynload', '/usr/lib/python2.6/dist-packages', '/usr/lib/pymodules/python2.6', '/usr/local/lib/python2.6/dist-packages', '/usr/local/lib/python2.6/dist-packages']
env.PYTHONHOME = '/usr:/usr/local'
env.PATH = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin'
当 apache2 在引导过程中从 /etc/rc2.d 启动时,它无法正确初始化,并且应用程序显示:
version 2.6.5 (r265:79063, Apr 16 2010, 14:15:55)
[GCC 4.4.3]
sys.prefix = '/usr'
sys.exec_prefix = '/usr/local'
sys.path = ['/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/local/lib/python2.6/lib-dynload']
env.PYTHONHOME = '/usr:/usr/local'
env.PATH = '/sbin:/usr/sbin:/bin:/usr/bin'
找不到关键目录,包括 dist-packages。
我尝试过在启动序列中将 apache 脚本移动到更早和更晚的位置,但结果都不好。在启动时最后加载 apache 会导致 sys.path 出现故障;从外壳加载它,然后立即正确加载。
问题又是,为什么 sys.path 初始化作为启动进程运行与从 shell 运行不同?
后续:
Python 的初始化并未运行 site.py。现在我看到 mod_wsgi 错误“无法导入‘site’模块”。在 Apach2.conf 中提供 WSGIPythonPath 值后,错误开始出现,尽管 sys.path 症状一直存在。
chroot Apache 和从 rc#.d 脚本启动的组合会破坏 Python 的 site.py 加载。
从全新帐户通过 sudo 或 sudo -i 从 shell 启动 Apache 效果很好。
I am using Python embedded in Apache using modwsgi, and I am finding that the sys.path does not get initialized correctly when Apache is started from the rc2.d startup folder than when run from the shell.
The versions:
Ubuntu Lucid 10.04
Apache 2.2
Python 2.6
mod_wsgi 3.3
Firstly, I am testing the initialization using this app:
import sys
import os
def application(environ, start_response):
status = '200 OK'
output = ['version %s\n'%sys.version]
output.append('sys.prefix = %s \n' % repr(sys.prefix))
output.append('sys.exec_prefix = %s \n' % repr(sys.exec_prefix))
output.append('sys.path = %s \n' % repr(sys.path))
output.append('env.PYTHONHOME = %s\n' % repr(os.environ.get('PYTHONHOME')))
output.append('env.PATH = %s\n' % repr(os.environ.get('PATH')))
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(sum([len(o) for o in output])))]
start_response(status, response_headers)
return output
When apache2 is started from bash, via 'sudo apache2ctl start', or 'sudo /etc/init.d/apache2 start', it initializes correctly, and the app above shows:
version 2.6.5 (r265:79063, Apr 16 2010, 14:15:55)
[GCC 4.4.3]
sys.prefix = '/usr'
sys.exec_prefix = '/usr/local'
sys.path = ['/usr/local/lib/python2.6/dist-packages/WebOb-1.0.7-py2.6.egg', '/usr/local/lib/python2.6/dist-packages/twiddler-0.9.1-py2.6.egg', '/usr/local/lib/python2.6/dist-packages/elementtree-1.2.7_20070827_preview-py2.6.egg', '/usr/local/lib/python2.6/dist-packages/lxml-2.3-py2.6-linux-x86_64.egg', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/local/lib/python2.6/lib-dynload', '/usr/lib/python2.6/dist-packages', '/usr/lib/pymodules/python2.6', '/usr/local/lib/python2.6/dist-packages', '/usr/local/lib/python2.6/dist-packages']
env.PYTHONHOME = '/usr:/usr/local'
env.PATH = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin'
When apache2 is started from /etc/rc2.d during boot, it does not initialize correctly, and the app shows:
version 2.6.5 (r265:79063, Apr 16 2010, 14:15:55)
[GCC 4.4.3]
sys.prefix = '/usr'
sys.exec_prefix = '/usr/local'
sys.path = ['/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/local/lib/python2.6/lib-dynload']
env.PYTHONHOME = '/usr:/usr/local'
env.PATH = '/sbin:/usr/sbin:/bin:/usr/bin'
Critical directories are not found, including dist-packages.
I have tried moving the apache script earlier and later in the startup sequence, and gotten uniformly bad results. Loading apache last in the startup gets the dysfunctional sys.path; loading it from the shell, immediately afterward, loads correctly.
The question, again, is why would the sys.path initialize differently run as a startup process than run from the shell?
Follow-up:
site.py is not being run by Python's initialization. Now I am seeing mod_wsgi errors "unable to import 'site' module". The errors started appearing after providing a WSGIPythonPath value in Apach2.conf, though the sys.path symptoms have been there all along.
There is something about the combination of chrooting Apache and starting from rc#.d scripts that is breaking Python's site.py loading.
Launching Apache from the shell, via sudo, or sudo -i, from a brand new account, works fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您正在以不同的用户身份运行。当您以标准用户身份运行时,Bash(以及您的其他登录脚本)会设置一些路径变量,而在启动时以 apache 用户身份运行时可能不会设置这些变量。
Apache 正在正确初始化。如果需要,您只需明确要包含哪些路径即可。
这与您在运行 cron 作业时经常需要更明确的原因相同。
当您使用 sudo 成为该用户时,现有环境的一部分将保留,包括您的 python 路径变量。您需要将 -i 选项与 sudo 一起使用来模拟 root 用户最初登录并运行 apache 时发生的情况。
http://www.gratisoft.us/sudo/man /1.8.0/sudo.man.html#i_command
You're running as a different user. Bash (and your other login scripts) set some of your path variables when you run as your standard user that may not get set when running as the apache user on startup.
Apache is initializing correctly. You just need to be explicit about which paths you want to include, if you need them.
It's the same reason you often need to be more explicit when running cron jobs.
When you use sudo to become that user, part of your existing environment persist, including your your python path variables. You need to use the -i option with sudo to simulate what happens when the root user initially logs in and runs apache.
http://www.gratisoft.us/sudo/man/1.8.0/sudo.man.html#i_command