База данных PHP Timezone повреждена - PullRequest
10 голосов
/ 06 января 2012

У меня есть сайт WordPress, который сегодня внезапно перестал работать. Когда я смотрю на логи, я вижу и ошибку:

[ошибка] [клиент 50.78.108.177] Неустранимая ошибка PHP: strtotime (): часовой пояс база данных повреждена - это не должно никогда случиться!

После прочтения в Google один человек сказал, что обнаружил проблему с правами доступа в / usr / share / zoneinfo . Я попытался изменить разрешения на 777, 775, 770, и я продолжаю получать ту же ошибку. Я использую php PHP 5.3.2 в Ubuntu 10.04.3 LTS. Любые предложения или рекомендации будут полезны. Если все остальное не поможет, я попытаюсь перейти на более раннюю версию 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 );
}

Update # 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 / WP-администратора / 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 возвращает

Дата сборки => 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. Я все еще получаю ошибку

Ответы [ 6 ]

20 голосов
/ 24 января 2013

Эта проблема также может возникать при использовании php-fpm в режиме chroot, решение в этом случае - создать что-то вроде / usr / share / zoneinfo / Europe в каталоге chroot, а затем скопировать в него файл TZ, например. Лондон

6 голосов
/ 29 января 2015

Основная причина: не удалось открыть один из файлов zoneinfo.

также вызвано : слишком много открытых файлов.

У меня сегодня была такая же проблемаУбунту 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 повреждено», но это просто означает, что процесс PHP не смог открыть эти файлы:

  • их там не было (chroot jail, ошибка установки zoneinfo)
  • их там не было, и не должно быть : "Europe / Roem" - не действительный часовой пояс, а опечатка.
  • они были там, но с неправильными разрешениями.
  • они были там, но процесс не авторизован (SELinux, AppArmor, ...)
  • они были там, но операция fopen временно не работает

Мой случай был последним: проблема real заключалась в том, что скрипт открывал слишком много временных файлов и оставлял их открытыми во время работы.Существует ограничение на количество файлов, которые могут быть открыты одновременно, и файл zoneinfo был последней пресловутой каплей.Быстрое исправление временно решило проблему, в то время как я передал проблему «слишком много файлов» ответственному разработчику.

На самом деле я подозреваю, что этот также указывает на PHP, постоянно открывающий и закрывающий базу данных zoneinfo.вместо кеширование это, но это расследование на другой день.

Прерывистая ошибка Количество "открытых файлов" составляет на процесс , не для скрипта PHP .Таким образом, существует два (по крайней мере) сценария, которые могут привести к трудно диагностируемой, возможно, прерывистой / невоспроизводимой ошибке:

  • медленная утечка ресурсов из-за какого-то длительного процесса, например, в Racket.
  • ресурс, захваченный другим скриптом или подпрограммой, работающей в том же процессе, и, возможно, даже не связанный с PHP вообще .

PHP-скрипт, который,правильно или неправильно, выделение 800 файлов может работать нормально, пока не встретится другой подпроцесс, который выделил 224 файла.Достигнуто ограничение в 1024 открытых файла на процесс, и в в этом случае процесс завершается с загадочной ошибкой (которая при этом загадочно относится к самому последнему признаку в длинной цепочке параллельных причин).

Apache: слишком много веб-сайтов.

Apache, работающий с mod_php5, приведет к открытию файлов, к которым обращается PHP, процессом Apache.Но процесс Apache также сохраняет свои файлы журнала открытыми, и каждый процесс имеет дескриптор для каждого файла журнала.

Так что если у вас есть 200 веб-сайтов, каждый с независимым access_log, скажем /var/www/somesite/logs/access_log, каждый процесс будет начинаться с 210 дескрипторов, уже занятых для ведения домашнего хозяйства, в результате чего около PHP будет свободно для использования.

.Производственный сервер (с 200 установленными сайтами) этого не делает, если сценарию необходимо выделить сразу 900 временных файлов.

Грязная диагностика (в Unix / Linux) : glob /proc/self/fdи count() результат.Ужасно, как грех, но он показывает приблизительное число открытых файловых дескрипторов.

Быстрое и грязное исправление (в Unix / Linux) : увеличение fdlimit при открытии каждого процессафайлы, доведя его до 1024 (конечно, вы должны быть root).Это скорее вопрос Ошибка сервера .

2 голосов
/ 10 января 2012

Проблема была в правах доступа к файлам. Я дал пользователю apache2 доступ для чтения и выполнения к usr / share / zoneinfo и т. Д. / Localtime. Раньше я не настраивал родителей местного времени на правильные разрешения. т.е. я только изменил разрешения localtime и zoneinfo без изменения разрешений их родительских каталогов. Так глупо! Отступить от проблемы и вернуться к ней всегда полезно.

1 голос
/ 06 января 2012

Вы упомянули «понижение рейтинга», вы недавно обновились?В 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после этого, чтобы убедиться, что информация о часовом поясе получена.

- Edit

Похоже, виновником является ваша функция date_i18n (), которая всегда вызывается, если только вызывающий код специально не передает 3-й аргументиз «ложного».Я проверил ваш код через некоторые тестовые данные с $ 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));
}
0 голосов
/ 30 мая 2018

Я изменяю файл местного времени для своей настройки GMT, например, mv / usr / share / zoneinfo / Asia / Karachi localtime. Затем происходит ошибка followinf.

date_default_timezone_get (): база данных часовых поясов повреждена - это не должно никогда случилось!

Решение: отменить настройку местного времени.Советы: Всегда сохраняйте резервную копию вашего старого местного времени, чтобы вы могли исправить любую ожидаемую проблему ОС / ПО

0 голосов
/ 06 января 2012

может быть, это может вам помочь PHP - Установить часовой пояс

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...