У меня есть сайт WordPress, который внезапно прекратил работать сегодня. Когда я смотрю на журналы, которые вижу и ошибки:
[error] [клиент 50.78.108.177] PHP Неустранимая ошибка: strtotime (): база данных часовых поясов повреждена – этого никогда не должно быть!
После чтения в Google один человек сказал, что они обнаружили проблему с разрешениями в / usr / share / zoneinfo . Я попытался изменить разрешения на 777, 775, 770, и я все равно продолжаю получать ту же ошибку. Я запускаю php PHP 5.3.2 на Ubuntu 10.04.3 LTS. Любые предложения или рекомендации были бы полезными. Если все остальное не работает, я собираюсь попытаться понизить до более ранней версии php, но я хотел попробовать другие вещи, прежде чем делать это.
спасибо, Тимнит
Обновить
на всякий случай это помогает: ошибка указывает на 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) строка «dmy» (1) строка «m» (5) строка «dmy» (1) строка «m» (5) строка «dmy» (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» строка ( 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 Неустранимая ошибка: дата (): база данных часовых поясов повреждена – этого никогда не должно быть! в /srv/www/motionthink.com/public_html/wp-admin/includes/class-wp-filesystem-direct.php в строке 346, референт: wp_root_directory / wp-admin / plugins.php? plugin_status = upgrade
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
php -i | fgrep -i date
возвращает php -i | fgrep -i date
Дата постройки => 13 Дек 2011 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, чтобы установить часовой пояс в «Америка / Лос-Анджелес» и получил этот вывод
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. Я все еще получаю ошибку
Эта проблема также может возникать при использовании php-fpm в режиме chroot, поэтому в этом случае нужно создать что-то вроде / usr / share / zoneinfo / Europe в вашем каталоге chroot, а затем скопировать в него файл TZ, например, в Лондоне
также вызвано : слишком большим количеством открытых файлов.
Сегодня у меня была та же проблема на 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 открытых файла на процесс, и в этом случае процесс завершится неудачей с таинственной ошибкой (которая относится только к ней с критической точки зрения к самому последнему симптому в длинной цепочке одновременных причин).
Apache, работающий с mod_php5
, заставит файлы, к которым обращается PHP, будет открыт процессом Apache. Но процесс Apache также сохраняет свои файлы журналов открытыми, и каждый процесс имеет дескриптор для каждого файла журнала.
Поэтому, если у вас есть 200 веб-сайтов, каждый из которых имеет независимый access_log, скажите /var/www/somesite/logs/access_log
, каждый процесс начнется с 210 дескрипторов, уже принятых для домашнего хозяйства, оставив около 800 бесплатных PHP для использования.
Это может привести к ситуации, когда работает сервер разработки (с одним сайтом), а на рабочем сервере (с 200 сайтами) нет, если скрипту необходимо одновременно выделить 900 временных файлов.
Грязная диагностика (в Unix / Linux) : glob
/proc/self/fd
и count()
результат. Уродливый как грех, но он дает приблизительную цифру о том, сколько файловых дескрипторов фактически открыто.
Быстрое и грязное исправление (в Unix / Linux) : увеличьте fdlimit для открытых файлов на каждом процессе, доведя его до 1024 (конечно, вам нужно быть root). Это скорее проблема Server Fault .
Проблема была в правах доступа к файлам. Я дал пользователю apache2 прочитать и выполнить доступ к usr / share / zoneinfo и т. Д. / Localtime. Раньше я не устанавливал родителей местного времени на правильные разрешения. т.е. я только изменил разрешения localtime и zoneinfo без изменения разрешений своих родительских каталогов. Так глупо! Уйти от проблемы и вернуться к ней всегда полезно.
Вы упоминаете «понижение», недавно вы обновили? В PHP 5.3.x вы вынуждены установить допустимое значение для date.timezone
в файле php.ini.
Если вы не обновляли обновление, попробуйте решить проблему, повторно установив пакет 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». Я проверил ваш код с помощью некоторых тестовых данных с $ translate set to 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' => 'dmy', 'mysqlstring' => '2011-10-20 05:35:01' ), array( 'dateformatstring' => 'm', 'mysqlstring' => '2011-10-20 05:35:01' ), array( 'dateformatstring' => 'dmy', '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)); }
может быть, это может помочь вам PHP – Установить часовую зону