什么原因导致 Apache 的时间/时区间歇性改变?

什么原因导致 Apache 的时间/时区间歇性改变?

我运行一个带有一些 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() 函数。

相关内容