我运行一个带有一些 PHP 论坛的服务器(香草1.1.5a),最近我注意到帖子的顺序乱了。经过一番挖掘,我发现 Apache 似乎在请求时将当前时区从 +0000 来回更改为 -0500,没有明显的模式,这可以在以下日志条目中看到:
38.104.58.202 - - [15/Jun/2009:22:40:05 +0000] "GET /extensions/MembersList/library/paginate.js HTTP/1.1" 200 22880 "http://mysite.com/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b99) Gecko/20090605 Firefox/3.5b99"
38.104.58.202 - - [15/Jun/2009:17:40:05 -0500] "GET /extensions/JQuery/jquery-1.2.6.min.js HTTP/1.1" 200 55804 "http://mysite.com/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b99) Gecko/20090605 Firefox/3.5b99"
虽然根据时区差异调整后的时间相同,但这似乎导致 PHP 的日期函数返回本地未调整的时间(从而导致论坛数据出现时间扭曲混乱)。
我还在同一个 VirtualHost 上运行基于 Django 的 mod_python 应用程序。配置如下:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog /var/log/apache2/access.log combined
Alias /doc/ "/usr/share/doc/"
<Directory "/usr/share/doc/">
Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128
</Directory>
Alias /media/ "/usr/share/python-support/python-django/django/contrib/admin/media/"
<Directory /usr/share/python-support/python-django/django/contrib/admin/media/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
RedirectMatch ^/raid-scheduler$ "/raid-scheduler/"
<Location "/raid-scheduler/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE raid_scheduler.settings
PythonOption django.root /raid-scheduler
PythonDebug On
PythonPath "['/opt', '/opt/raid_scheduler'] + sys.path"
</Location>
</VirtualHost>
对于可能造成这种情况的原因有什么想法吗?
答案1
可能是其他请求正在设置 TZ,而它却被搁置了?getenv('TZ')
在每个请求开始时记录将验证这一点,并可putenv
用于解决此问题。
答案2
在 Unix/Linux 中,每个进程可以在不同的时区中运行。这是因为根据进程环境中可能存在的 $TZ 变量的内容,与系统时间相关的函数会更改其返回值(这既不是 PHP 特有的,也不是 Apache 特有的)。您的一个或多个 Apache 进程中可能正在修改 $TZ。mod_php 和 mod_python 都是 Apache 进程的一部分,因此它们可以自由修改 $TZ。
您能否通过 posix_getpid() 将 getenv('TZ') 与 Apache 进程 id 一起打印到日志中,以便用它来匹配各种用户请求?
答案3
我认为这与您的 php 设置有更多关系。请查看 mod_php“TZ”环境变量。
答案4
TZ 环境变量以及与语言和区域设置相关的各种环境变量都是进程全局变量。因此,在同一进程中运行多个应用程序实例(无论是 Python 还是 PHP)并希望对其进行不同设置将导致问题。此问题还会影响 mod_wsgi,并在以下部分进行了讨论:
http://code.google.com/p/modwsgi/wiki/ApplicationIssues#Timezone_and_Locale_Settings
请注意,尝试通过从 Python Web 应用程序内部查看 os.environ 来验证某些内容可能无济于事,因为 os.environ 是创建 Python(子)解释器实例时进程环境变量的副本。因此,对 TZ 或其他环境变量的任何更改都不会反映在 Python os.environ 字典中。特定值的同步仅在 os.environ 中的值更新时发生,在这种情况下,Python 还会调用 C 级 putenv() 函数。