Intereting Posts
Можно ли изменить ширину табуляции (\ t) в строке PHP? Как передать переменные как stdin в командной строке из PHP Уведомления GCM не принимаются, когда приложение находится в фоновом режиме в iOS Как установить кодировку для UTF-8 для полученной переменной http в PHP? Есть ли способ отключить покрытие кода в PHPUnit для одного теста? PhpDoc для интерфейса и интерфейса реализации класса – разница PHP cURL GET запрос и тело запроса Извлечение полей MySQL из строки в переменные и массив PHP Подобные изображения – как их сравнить Не проверять, не сделан ли пользователь Можно ли уменьшить переменную в MySQL? Устранение неполадок "ошибка синтаксического анализа, неожиданная ошибка"> " Защищенные от PHP классы и свойства, защищенные от кого? как сбросить форму после отправки? Какова рекомендуемая практика для API-интерфейса PayPal NVP с остановкой и возвратом подписки?

База данных часовых поясов PHP является поврежденной ошибкой

У меня есть сайт 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, например, в Лондоне

Корневая причина: один из файлов zoneinfo не может быть открыт.

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

Сегодня у меня была та же проблема на 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 не смог открыть эти файлы:

  • их не было (chroot jail, zoneinfo install error)
  • их не было, и не должно быть : «Европа / Роем» не является допустимым часовым поясом, а опечаткой.
  • они были там, но с неправильными разрешениями.
  • они были там, но процесс не разрешен (SELinux, AppArmor, …)
  • они были там, но операция fopen временно не работает

Мое дело было последним: реальная проблема заключалась в том, что скрипт открыл слишком много временных файлов и оставил их открытыми во время работы. Существует ограничение на то, сколько файлов можно открыть одновременно, а файл 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 дескрипторов, уже принятых для домашнего хозяйства, оставив около 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 – Установить часовую зону