2011-01-20 8 views
9

El código en el que estoy trabajando funciona perfectamente en Windows XP y en Mac OS X. Cuando se prueba en CentOS (y en Fedora y Ubuntu), no funciona correctamente. La búsqueda en las redes me llevó a la conclusión de que es la versión glibc del iconv la que está causando el problema. Así que ahora necesito la versión libiconv de iconv para que Zend Lucene funcione correctamente.¿Cómo puedo forzar a PHP a usar la versión libiconv de iconv en lugar de la versión glibc instalada en CentOS?

Ya descargué libiconv y lo configuré con --prefix=/usr/local, make, luego make install sin ningún error. Parece que se instaló correctamente porque al ejecutar /usr/local/bin/iconv --version dice que la versión es libiconv. Aunque un simple iconv --version todavía da la versión glibc.

Luego recompuse PHP de la fuente usando --with-iconv=/usr/local. Pero aún así, el phpinfo() muestra que el iconv que se está utilizando es la versión glibc. También he probado otras compilaciones usando --with-iconv-dir o usando /usr/local/bin/php.

Por supuesto, reinicié el servidor web después de recompilar PHP.

que tienen la siguiente línea en mi /etc/httpd/conf/httpd.conf:

LoadModule /usr/lib/httpd/modules/libphp5.so 

y libphp5.so está realmente en /usr/lib/httpd/modules.

phpinfo() muestra PHP 5.3.3. También eliminé el PHP 5.1 preinstalado * solo para asegurarme. Pero iconv todavía usa la versión glibc.

ldd /usr/lib/httpd/modules/libphp5.so da

linux-gate.so.1 => (0x003b1000) 
/usr/local/lib/preloadable_libiconv.so (0x00110000) 
libcrypt.so.1 => /lib/libcrypt.so.1 (0x001ed000) 
librt.so.1 => /lib/librt.so.1 (0x0021f000) 
libmysqlclient.so.15 => /usr/lib/mysql/libmysqlclient.so.15 (0x003b2000) 
libldap-2.3.so.0 => /usr/lib/libldap-2.3.so.0 (0x0026e000) 
liblber-2.3.so.0 => /usr/lib/liblber-2.3.so.0 (0x00370000) 
libiconv.so.2 => /usr/local/lib/libiconv.so.2 (0x00516000) 
libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x002a8000) 
libpng12.so.0 => /usr/lib/libpng12.so.0 (0x00228000) 
libz.so.1 => /usr/lib/libz.so.1 (0x00328000) 
libcurl.so.3 => /usr/lib/libcurl.so.3 (0x00f23000) 
libm.so.6 => /lib/libm.so.6 (0x0033b000) 
libdl.so.2 => /lib/libdl.so.2 (0x00364000) 
libnsl.so.1 => /lib/libnsl.so.1 (0x0037e000) 
libxml2.so.2 => /usr/lib/libxml2.so.2 (0x00f5f000) 
libssl.so.6 => /lib/libssl.so.6 (0x0862c000) 
libcrypto.so.6 => /lib/libcrypto.so.6 (0x04145000) 
libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x08e2d000) 
libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x0611a000) 
libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x005f4000) 
libcom_err.so.2 => /lib/libcom_err.so.2 (0x0024e000) 
libidn.so.11 => /usr/lib/libidn.so.11 (0x071f5000) 
libc.so.6 => /lib/libc.so.6 (0x08aa6000) 
libpthread.so.0 => /lib/libpthread.so.0 (0x00397000) 
/lib/ld-linux.so.2 (0x00251000) 
libresolv.so.2 => /lib/libresolv.so.2 (0x0748a000) 
libsasl2.so.2 => /usr/lib/libsasl2.so.2 (0x07ddf000) 
libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0x062b7000) 
libkeyutils.so.1 => /lib/libkeyutils.so.1 (0x00369000) 
libselinux.so.1 => /lib/libselinux.so.1 (0x0913b000) 
libsepol.so.1 => /lib/libsepol.so.1 (0x07eb4000) 

Esta es una cruz-puesto de: NullPointer.ph

+0

¿Qué muestra 'ldd/usr/lib/httpd/modules/libphp5.so' y' ldd/usr/libexec/httpd/httpd'? AFAIK, apache también depende de 'libiconv'. No puede cargar dos versiones de 'libiconv' en un proceso. –

+0

Pregunta actualizada para reflejar 'ldd/usr/lib/httpd/modules/libphp5.so'. El segundo comando me da un 'No dicho archivo o directorio'. – Randell

+0

intente configurar con '--with-iconv = shared,/usr/local' – ismail

Respuesta

9

Acabo de cambiar mi php-5.3.3 de glibc's iconv a GNU libiconv mediante la compilación manual de la extensión php iconv. Siga estos pasos:

  1. descarga php-5.3.3 source code paquete
  2. extraerlo y entrar en php-5.3.3/ext/iconv subdirectorio
  3. ejecutar phpize comando (si no tiene tales comandos a continuación, instalar php-devel paquete)
  4. archivo

    (*) editar configure (vim configure): añadir iconv_impl_name="" en 4664 la línea (número de línea exacta de la configuración del sistema puede ser diferente):

    ... 
    iconv_impl_name="" 
        if test -z "$iconv_impl_name"; then 
         { $as_echo "$as_me:${as_lineno-$LINENO}: checking if using GNU libiconv" >&5< 
    ... 
    
  5. ./configure --with-iconv=/usr/local|grep iconv:

    checking if using GNU libiconv... yes 
    
  6. make

  7. sudo make install

Y ahora funciono php -i|grep "iconv impl" y tiene:

iconv implementation => libiconv 

* Esto obliga truco configurar para seleccionar el libiconv GNU en lugar de iconv de glibc. Por defecto, comprueba el iconov de glibc en el primer paso y no comprueba en absoluto si hay GNU libiconv.

+0

¡Funcionó f * ckn! – Randell

+1

Me hace preguntarme por qué glibc es la implementación predeterminada que se usa para Linux, mientras que libiconv es el predeterminado para Mac y Windows. – Randell

+1

Solo una cabeza arriba - no estoy seguro de si hace alguna diferencia, pero el método anterior no funcionó para mí al intentar compilar PHP 5.3.8 desde la fuente, ya que la configuración ./configure de PHP principal no se levantó o honrar el cambio de la secuencia de comandos ext/iconv/configure. Así que seguí adelante e hice que el cambio anterior fuera el guión principal ./configure en el directorio php-5.3.8 de nivel superior, y funcionó a las mil maravillas. ¡Gracias! –

-1

No sé sobre CentOS, pero en distribuciones basadas en Debian, como Ubuntu, se puede elegir la versión del programa que desea definir los enlaces simbólicos en/etc/alternatives.

Por lo tanto, si cambia el enlace symbolink/etc/alternatives/iconv para apuntar a/usr/local/bin/iconv, este punto debe usar la versión correcta.

http://www.debian-administration.org/articles/91

+0

Esto podría valer la pena intentarlo. Voy a publicar una actualización más tarde. – Randell

+5

'/ etc/alternatives' se aplica a los archivos ejecutables, no a las bibliotecas. – jilles

0

¿Estas seguro que LD_LIBRARY_PATH está correctamente configurado para proceso httpd (servidor web)? Si no es así, intente configurarla como:

export LD_LIBRARY_PATH="/usr/local/lib:${LD_LIBRARY_PATH}" 

... en el guión que se inicia el proceso (es decir apachectl).

La salida ldd que mostró parece correcta, pero ha invocado ldd desde el entorno del usuario, y httpd puede ser diferente.

También podría ayudar establecer PATH en "/ usr/local/bin: $ {PATH}", por las dudas.

+0

Ejecuto 'export LD_LIBRARY_PATH ="/usr/local/lib: $ {LD_LIBRARY_PATH} "' pero nada ha cambiado. – Randell

9

Su módulo (libphp5.so) está vinculado a dos bibliotecas compartidas que están ofreciendo el mismo símbolo (en este caso el símbolo es iconv y las bibliotecas son libiconv.so.2 y probablemente libc.so.6).

Cuando esto sucede, se utiliza el primer símbolo cargado: probablemente libc.so.6 se carga antes que libiconv.so.2 y por lo tanto es el que le proporciona el símbolo iconv.

Puede forzar el cargador dinámico para cargar una biblioteca antes que cualquier otra; puede hacer esto configurando la variable de entorno LD_PRELOAD en la biblioteca que desea precargar.

No soy un experto en Apache, así que no estoy totalmente seguro de cómo funciona, cómo comienza su proceso y qué procesos utiliza, pero creo que establecer LD_PRELOAD antes de ejecutar Apache debería ser el truco:

LD_PRELOAD=/usr/local/lib/libiconv.so.2 

un pequeño ejemplo para mostrar LD_PRELOAD en acción:

compilará myfopen.c como una biblioteca compartida (myfopen.so): se proporcionará un símbolo fopen (ya se define en libc):

$ cat myfopen.c 
int fopen(const char *path, const char *mode){ return -1; } 
$ gcc -o libmyfopen.so myfopen.c -shared 

Compilar printfopen.c como un ejecutable (printfopen), que sólo imprime el resultado de fopen; enlazará contra tanto libc y libmyfopen (LD_LIBRARY_PATH que se necesita para que el aspecto enlazador para las bibliotecas también en .):

$ cat printfopen.c 
#include <stdio.h> 
int main() { 
    printf("%d\n", fopen("","")); 
    return 0; 
} 
$ gcc -o printfopen printfopen.c -L. -lmyfopen 
$ LD_LIBRARY_PATH=. ldd printfopen 
    linux-gate.so.1 => (0xb779d000) 
    libmyfopen.so => ./libmyfopen.so (0xb779a000) 
    libc.so.6 => /lib/libc.so.6 (0xb762f000) 
    /lib/ld-linux.so.2 (0xb779e000) 

Ahora estoy corriendo, para probar si LD_PRELOAD obras:

$ LD_LIBRARY_PATH=. ./printfopen 
-1 
$ LD_PRELOAD=/lib/libc.so.6 LD_LIBRARY_PATH=. ./printfopen 
0 
$ LD_PRELOAD=libmyfopen.so LD_LIBRARY_PATH=. ./printfopen 
-1 

Por defecto carga libmyfopen antes de libc, luego intenté forzar la carga de libc y luego libmyfopen primero.

Supongo que en su caso libc se está cargando antes de libiconv porque el primero lo carga la aplicación (apache?) Antes de cargar el módulo de PHP.

+0

Ejecuto 'LD_PRELOAD =/usr/local/lib/libiconv.so.2', y he reiniciado apache httpd pero iconv todavía está usando la implementación de glibc. ¿Qué me estoy perdiendo? – Randell

+0

@Randell: ¿está seguro de que los procesos que cargan el módulo PHP se han iniciado con la variable de entorno 'LD_PRELOAD' establecida correctamente? Intente e inspeccione PHP env vars. ¿Quizás el script de inicio de apache reinicie el entorno antes de iniciar Apache Daemon? – peoro

+0

¿Cómo verifico esto? – Randell

0

Entiendo que esta pregunta ya está respondida y casi muerta, pero recientemente traté de encontrar una forma de compilar PHP con libiconv porque en PHP no pude convertir "∙" de UTF8 a CP1251 incluso con iconv // IGNORAR. Pero he encontrado otra solución que funcionó para mí sin recompilación (sólo tiene que utilizar // TRANSLIT):

iconv ("UTF-8", "CP1251 // // TRANSLIT IGNORE", $ texto)

// TRANSLIT transliterará SOLAMENTE caracteres desconocidos (no todos, como algunos pueden adivinar), por lo que convierte el ruso 'ё', pero transcribe el desconocido '∙' a 0x95 (que se ve igual en el juego de caracteres del destino).

+0

Lamentablemente, no está muerto. – sjas

Cuestiones relacionadas