我运行一个服务器,上面有一些 PHP 驱动的论坛(Vanilla 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>
关于可能导致这种情况的任何想法?
可能是其他一些请求正在设置 TZ 并且它被遗弃了吗?
getenv('TZ')
在每个请求的开头记录可以验证这一点,并且putenv
可以用来解决它。在 Unix/Linux 中,每个进程都可以在不同的时区运行。这是因为根据进程环境中可能存在的 $TZ 变量的内容,系统时间相关函数会更改它们的返回值(这既不是 PHP 特定的,也不是 Apache 特定的)。可能 $TZ 在您的一个或多个 Apache 进程中被修改。mod_php 和 mod_python 都是 Apache 进程的一部分,因此它们可以自由修改 $TZ。
您可以通过 posix_getpid() 将 getenv('TZ') 与 Apache 进程 ID 一起打印到日志中,以便用于匹配各种用户请求吗?
我认为这与您的 php 设置有关。查看 mod_php "TZ" 环境变量。
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() 函数。