2012-01-05 8 views
9

Tengo un sitio web de wordpress que de repente dejó de funcionar hoy. Cuando miro a los registros que veo y error:PHP La base de datos de la zona horaria es un error corrupto

[error] [client 50.78.108.177] PHP Fatal error: strtotime(): Timezone database is corrupt - this should never happen!

Después de leer en Google una persona dijo que descubrieron un problema de permisos en /usr/share/zoneinfo. Traté de cambiar los permisos a 777, 775, 770 y sigo recibiendo el mismo error. Estoy ejecutando php PHP 5.3.2 en Ubuntu 10.04.3 LTS. Cualquier sugerencia o recomendación sería útil. Si todo lo demás falla, intentaré cambiar a una versión anterior de php, pero quería probar otras cosas antes de hacerlo.

gracias, Timnit

actualización
en caso de que ayuda a: los puntos de error a strtotime en la función de abajo

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); 
} 

Actualización # 2:
por ahora Se ha solucionado el problema simplemente teniendo la función por encima de return false; sin realizar nada. Sin embargo, todavía no he descubierto la causa raíz del problema.

actualización # 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"

actualización # 4:
hay otro fragmento de código que genera el registro de errores a continuación:

PHP Fatal error: date(): Timezone database is corrupt - this should never happen! in /srv/www/motionthink.com/public_html/wp-admin/includes/class-wp-filesystem-direct.php on line 346, referer: 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 

Actualización # 5:
haciendo un php -i | fgrep -i date vuelve

Build Date => Dec 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 

entonces editar el archivo php.ini para configurar la zona horaria a "América/Los Ángeles" y consiguieron esta salida

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 

Luego reinicié apache2. Todavía consigo el error

Respuesta

2

El problema es permisos de archivos. Le di al usuario de apache2 que lea & ejecute el acceso a usr/share/zoneinfo y etc/localtime. Antes, tampoco había configurado a los padres de la hora local los permisos adecuados. es decir, solo cambié los permisos de localtime e zoneinfo sin cambiar los permisos de sus directorios principales. ¡Tan estupido! Alejarse de un problema y volver a él siempre es útil.

+0

* panda triste *, toda esa depuración:/ –

0

puede haber esto puede ayudarle a PHP – Set Timezone

+0

gracias por eso. Cuando sigo las instrucciones, muestra la fecha: Jue, 05 Ene 2012 15:20:54 –

1

Usted menciona 'degradación', ¿Acaba de actualizar? En PHP 5.3.x está obligado a establecer un valor válido para date.timezone en su archivo php.ini.

Si no actualizó recientemente, intente resolver el problema volviendo a instalar el paquete tzdata. Trabajo exclusivamente con CentOS, así que no estoy seguro de cuál es el nombre del administrador de paquetes de Ubuntu, pero estoy bastante seguro de que tzdata es estándar en todas las distribuciones.

$ -> 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 

Es posible que desee reiniciar el httpd después de esta información para asegurarse de zona horaria es recogido.

- Editar

Parece que el culpable es su función date_i18n(), que siempre se está llamando, llamando a no ser que el código pasa específicamente a un tercio de arg 'falso'. Ejecuté su código a través de algunos datos de prueba con $ translate establecido en falso, y funcionó bien.

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

+0

lo siento, quise decir que piensas que todavía debo volver a instalar tzdata, aunque el guión php en mi comentario anterior haya devuelto la fecha? Además, recientemente realicé una actualización de apt-get –

+0

Volví a instalar tzdata (apt-get install --reinstall tzdata) y me dice que la hora local es ahora: Thu Jan 5 15:39:24 PST 2012. La hora universal es ahora: jue 5 de enero 23:39:24 UTC 2012. –

13

Este problema también puede ocurrir al usar php-fpm en modo chroot, la solución en este caso es crear algo como/usr/share/zoneinfo/Europe en el directorio chroot y luego copiar el archivo TZ en él, p. Londres

+0

Impresionante, esto es exactamente lo que necesitaba después de cerrar mi servidor Apache y solo ciertos guiones PHP se estaban rompiendo. Encendiendo el registro de errores encontré que este era el problema (aunque simplemente copié todo de '/ usr/share/zoneinfo/*' en mi jaula chroot). – Breakthrough

6

Causa raíz: uno de los archivos de zona no se pudo abrir.

también causado por: demasiados archivos abiertos.

Tuve el mismo problema hoy en Ubuntu 14.04.01-LTS "Trusty Tahr", y probé las otras respuestas sin ningún beneficio. Los permisos estaban bien, los archivos estaban allí, el contenido era el esperado.

Por fin resolví ejecutar el script desde dentro de un arnés de línea de comando, para poder probar con strace. Y este fue el resultado:

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 

Lo que está sucediendo

Cuando PHP "accede a la base de datos de información de zonas" que en realidad trata de abrir un directorio y algunos archivos. Si algunas de estas operaciones falla, el "zoneinfo corrupta" aparece, sino que simplemente significa que el proceso PHP no pudo abrir esos archivos:

  • que no estaban allí (jaula chroot, información de zonas error de instalación)
  • no estaban allí, ni deberían ser: "Europa/Roem" no es una zona horaria válida, sino un error tipográfico.
  • estaban allí, pero con permisos erróneos.
  • que estaban allí, pero el proceso no está autorizado (SELinux, AppArmor, ...)
  • que estaban allí, pero la operación fopen temporalmente no funciona

Mi caso fue el último : el problema real era que la secuencia de comandos era abriendo demasiados archivos temporales, y dejándolos abiertos durante la ejecución. Hay un límite en la cantidad de archivos que se pueden abrir al mismo tiempo, y el archivo zoneinfo fue el colmo proverbial.Una solución rápida resolvió el problema de forma temporal mientras rebotaba el problema de "demasiados archivos" al desarrollador responsable.

En realidad, yo sospecho que esto también puntos a PHP apertura y cierre de la base de datos de información de zonas de almacenamiento en caché en lugar de continuamente, pero es una investigación para otro día.

de error intermitente El "número de archivos abiertos" cosita es por proceso, no por script PHP. Así que hay dos (al menos) los escenarios de lo que podría conducir a un/error no reproducible difíciles de diagnosticar, posiblemente intermitente:

  • una pérdida de recursos lento por algún proceso de larga ejecución, por ejemplo, bajo raqueta.
  • recurso ocupado por otro script o subrutina ejecutándose en el mismo proceso, y posiblemente ni siquiera relacionado con PHP.

Un script PHP que, correcto o incorrecto, asigna 800 archivos podría funcionar bien hasta que se encuentre con otro subproceso que haya asignado 224 archivos. Se alcanza el límite de 1024 archivos abiertos por proceso y en ese caso el proceso falla con un error misterioso (que solo se refiere, crípticamente a eso, al último síntoma en una larga cadena de causas concurrentes).

Apache: demasiados sitios web.

Apache ejecutándose con mod_php5 hará que los archivos accedidos por PHP sean abiertos por el proceso de Apache. Pero el proceso de Apache también mantiene abiertos sus archivos de registro , y cada proceso tiene un identificador para cada archivo de registro.

Así que si tiene 200 sitios web, cada uno con un access_log independiente, digamos /var/www/somesite/logs/access_log, cada proceso comenzará con 210 identificadores ya administrados, dejando unos 800 gratis para PHP.

Esto puede llevar a una situación donde el servidor de desarrollo (con un sitio) funciona, y el servidor de producción (con 200 sitios instalados) no lo hace, si el script necesita asignar 900 archivos temporales a la vez.

diagnóstico sucios (en Unix/Linux): glob/proc/self/fdcount() y el resultado. Feo como el pecado, pero da una cifra aproximada de cuántos descriptores de archivos están realmente abiertos.

Arreglo rápido y sucio (en Unix/Linux): aumente el fdimit en los archivos abiertos por proceso, llevándolo a 1024 (por supuesto, debe ser root). Es más una cuestión de Server Fault.

+0

De hecho, este fue el caso, cuando estaba codificando un cargador con soporte de partes y simultaneidad. –

Cuestiones relacionadas