我有一个wordpress网站,今天突然停止工作。当我查看日志时,我看到并出错:
[error] [client 50.78.108.177] PHP致命错误:strtotime():时区 数据库已损坏 - 这应该从不发生!
在谷歌上阅读后,有人说他们在 / usr / share / zoneinfo 中发现了权限问题。我尝试将权限更改为777,775,770,我仍然继续得到相同的错误。我在Ubuntu 10.04.3 LTS上运行php PHP 5.3.2。任何建议或建议都会有所帮助。如果其他所有方法都失败了,我会尝试降级到早期版本的php,但我还是想在尝试之前尝试其他的东西。
感谢, Timnit
更新
以防它有帮助:错误指向下面函数中的strtotime
function mysql2date( $dateformatstring, $mysqlstring, $translate = true ) {
$m = $mysqlstring;
if ( empty( $m ) )
return false;
if ( 'G' == $dateformatstring )
return strtotime( $m . ' +0000' );
$i = strtotime( $m );
if ( 'U' == $dateformatstring )
return $i;
if ( $translate )
return date_i18n( $dateformatstring, $i );
else
return date( $dateformatstring, $i );
}
更新#2:
现在我通过简单地使用return false;
以上的函数而不执行任何操作来解决问题。但是我仍然没有找出问题的根本原因。
更新#3:
var_dump($dateformatstring)
string(5)“d.m.y”string(1)“m”string(5)“d.m.y”string(1)“m” string(5)“d.m.y”string(1)“m”
var_dump($mysqlstring)
string(19)“2011-10-20 05:35:01”string(19)“2011-10-20 05:35:01” string(19)“2011-10-20 05:25:22”string(19)“2011-10-20 05:25:22” string(19)“2011-10-19 05:10:06”string(19)“2011-10-19 05:10:06”
更新#4 :
还有另一个代码片段,它生成以下错误日志:
PHP致命错误:date():时区数据库已损坏 - 这应该是 从不发生!在/srv/www/motionthink.com/public_html/wp-admin/includes/class-wp-filesystem-direct.php 在第346行,引用者: wp_root_directory /可湿性粉剂管理员/ plugins.php?plugin_status =升级
309 function dirlist($path, $include_hidden = true, $recursive = false) {
310 if ( $this->is_file($path) ) {
311 $limit_file = basename($path);
312 $path = dirname($path);
313 } else {
314 $limit_file = false;
315 }
316
317 if ( ! $this->is_dir($path) )
318 return false;
319
320 $dir = @dir($path);
321 if ( ! $dir )
322 return false;
323
324 $ret = array();
325
326 while (false !== ($entry = $dir->read()) ) {
327 $struc = array();
328 $struc['name'] = $entry;
329
330 if ( '.' == $struc['name'] || '..' == $struc['name'] )
331 continue;
332
333 if ( ! $include_hidden && '.' == $struc['name'][0] )
334 continue;
335
336 if ( $limit_file && $struc['name'] != $limit_file)
337 continue;
338
339 $struc['perms'] = $this->gethchmod($path.'/'.$entry);
340 $struc['permsn'] = $this->getnumchmodfromh($struc['perms']);
341 $struc['number'] = false;
342 $struc['owner'] = $this->owner($path.'/'.$entry);
343 $struc['group'] = $this->group($path.'/'.$entry);
344 $struc['size'] = $this->size($path.'/'.$entry);
345 $struc['lastmodunix']= $this->mtime($path.'/'.$entry);
346 $struc['lastmod'] = date('M j',$struc['lastmodunix']);
347 $struc['time'] = date('h:i:s',$struc['lastmodunix']);
348 $struc['type'] = $this->is_dir($path.'/'.$entry) ? 'd:'f';
349
更新#5:
执行php -i | fgrep -i date
返回
构建日期=> 2011年12月13日18:43:02
date date/time support => enabled date.default_latitude => 31.7667 => 31.7667 date.default_longitude => 35.2333 => 35.2333 date.sunrise_zenith => 90.583333 => 90.583333 date.sunset_zenith => 90.583333 => 90.583333 date.timezone => no value => no value
然后我编辑了php.ini文件,将时区设置为“America / Los Angeles”并获得此输出
date/time support => enabled
date.default_latitude => 31.7667 => 31.7667
date.default_longitude => 35.2333 => 35.2333
date.sunrise_zenith => 90.583333 => 90.583333
date.sunset_zenith => 90.583333 => 90.583333
date.timezone => America/Los_Angeles => America/Los_Angeles
然后我重新启动了apache2。我仍然收到错误
答案 0 :(得分:20)
在chroot模式下使用php-fpm时也会出现此问题,在这种情况下,解决方案是在chroot目录中创建类似/ usr / share / zoneinfo / Europe的内容,然后将您的TZ文件复制到其中,例如伦敦
答案 1 :(得分:6)
也是由引起的:打开的文件过多。
我今天在Ubuntu 14.04.01-LTS“Trusty Tahr”上遇到了同样的问题,并尝试了其他答案而没有任何好处。权限还可以,文件在那里,内容与预期一致。
最后我决定从命令行工具中运行脚本,以便我可以尝试使用strace
。这就是结果:
openat(AT_FDCWD, "/usr/share/zoneinfo/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 EMFILE (Too many open files)
open("/usr/share/zoneinfo/zone.tab", O_RDONLY) = -1 EMFILE (Too many open files)
stat("/usr/share/zoneinfo/Europe/Rome", {st_mode=S_IFREG|0644, st_size=2652, ...}) = 0
open("/usr/share/zoneinfo/Europe/Rome", O_RDONLY) = -1 EMFILE (Too many open files)
write(1, "\nFatal error: Unknown: Timezone "..., 104) = 104
发生了什么
当PHP“访问zoneinfo数据库”时,它实际上会尝试打开目录和一些文件。如果其中一些操作失败,则会显示“zoneinfo corrupt”消息,但这只表示PHP进程无法打开这些文件:
fopen
操作暂时无法正常工作我的情况是最后一个:真正的问题是脚本打开了太多临时文件,并在运行时让它们保持打开状态。可以同时打开多少文件是有限制的,而zoneinfo文件是众所周知的最后一根稻草。当我向负责的开发人员反复出现“太多文件”问题时,快速修复可以暂时解决问题。
实际上我怀疑这个也指向PHP不断打开和关闭zoneinfo数据库而不是缓存它,但这是另一天的调查。
间歇性错误 “打开文件的数量”是每个进程,而不是每个PHP脚本。因此,有两个(至少)情景可能导致难以诊断,可能是间歇性/不可重现的错误:
一个PHP脚本,无论是对还是错,分配800个文件都可以正常工作,直到遇到另一个分配了224个文件的子进程。达到了每个进程1024个打开文件的限制,并且在这种情况下该进程失败并出现一个神秘的错误(仅在此处隐含地指向长链并发原因中的最后一个症状)
使用mod_php5
运行的Apache将导致PHP访问的文件被Apache进程打开。但Apache进程也会保持其日志文件打开,并且每个进程都有一个每个日志文件的句柄。
因此,如果您有200个网站,每个网站都有一个独立的access_log,比如说/var/www/somesite/logs/access_log
,每个进程都会从已经用于管理的210个句柄开始,剩下800个免费供PHP使用。
如果脚本需要一次分配900个临时文件,这可能会导致开发服务器(带有一个站点)工作,生产服务器(安装了200个站点)不工作的情况。
脏诊断(在Unix / Linux上):glob
/proc/self/fd
和count()
结果。丑陋如罪,但它给出了实际打开多少文件描述符的大概数字。
快速而肮脏的修复(在Unix / Linux上):增加每个进程打开文件的fdlimit,使其达到1024(当然你需要是root用户)。这更像是Server Fault的问题。
答案 2 :(得分:2)
问题是文件权限。我给了apache2用户read&执行对usr / share / zoneinfo和etc / localtime的访问。之前,我还没有将当地时间的父母设置为正确的权限。即我只更改了localtime和zoneinfo的权限,而没有更改其父目录的权限。如此愚蠢!摆脱问题并回到它总是有用的。
答案 3 :(得分:1)
你提到'降级',你最近升级了吗?在PHP 5.3.x中,您必须在php.ini文件中为date.timezone
设置有效值。
如果您最近没有升级,请尝试通过重新安装tzdata
包来解决此问题。我专门使用CentOS,所以我不确定Ubuntu的包管理器的名称是什么,但我很确定tzdata
是发行版的标准。
$ -> yum reinstall tzdata # switch 'yum' for Ubuntu package manager
$ -> rm -f /etc/localtime
$ -> ln -sf /usr/share/zoneinfo/UTC /etc/localtime # 'UTC' can be replaced with what you prefer
$ -> date # check to see that it stuck
您可能需要在此之后重新启动httpd,以确保选择时区信息。
- 编辑
看起来罪魁祸首是你的date_i18n()函数,它总是被调用,除非调用代码专门传递第三个'false'的arg。我将代码运行一些测试数据,并将$ translate设置为false,并且工作正常。
function mysql2date( $dateformatstring, $mysqlstring, $translate = true ) {
$translate = false;
...
if ( $translate )
return 'date_i18n would have been called';
//return date_i18n( $dateformatstring, $i );
...
}
$testPatterns = array(
array(
'dateformatstring' => 'd.m.y',
'mysqlstring' => '2011-10-20 05:35:01'
),
array(
'dateformatstring' => 'm',
'mysqlstring' => '2011-10-20 05:35:01'
),
array(
'dateformatstring' => 'd.m.y',
'mysqlstring' => '2011-10-20 05:25:22'
)
);
foreach ($testPatterns as $testPattern) {
// Not passing arg to over-ride $translate, forces call to date_i18n()
var_dump(mysql2date($testPattern['dateformatstring'], $testPattern['mysqlstring']));
// Forcing $translate to false, makes date() call which works fine
var_dump(mysql2date($testPattern['dateformatstring'], $testPattern['mysqlstring'], false));
}
答案 4 :(得分:0)
可能会对您有所帮助PHP – Set Timezone
答案 5 :(得分:0)
我更改了我的GMT设置的localtime文件 mv / usr / share / zoneinfo /亚洲/卡拉奇当地时间 然后发生以下错误。
date_default_timezone_get():时区数据库已损坏 - 这应该从不发生!
解决方案:恢复您当地的时间设置。 提示:始终保留旧本地时间的备份副本,以便您可以恢复任何预期的操作系统/软件问题