2011-01-20 94 views
9

我正在使用的代码在Windows XP和Mac OS X上完美运行。在CentOS(以及Fedora和Ubuntu)上测试时,它无法正常工作。搜索网络导致我得出结论,这是导致问题的glibc版本iconv。所以现在我需要使用libiconv版本的iconv来让Zend Lucene正常工作。如何强制PHP使用iconv的libiconv版本而不是CentOS安装的glibc版本?

我已经下载了libiconv并将它配置为--prefix=/usr/localmake,然后make install没有任何错误。它似乎已成功安装,因为执行/usr/local/bin/iconv --version表示版本是libiconv。尽管简单的iconv --version仍然给出glibc版本。

然后我使用--with-iconv=/usr/local从源代码重新编译PHP。但仍然,phpinfo()显示iconv正在使用的是glibc版本。我也已经尝试过使用--with-iconv-dir或使用/usr/local/bin/php进行其他编译。

当然,我重新编译PHP后重新启动了Web服务器。

我在/etc/httpd/conf/httpd.conf以下行:

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

libphp5.so实际上是/usr/lib/httpd/modules

phpinfo()显示PHP 5.3.3。我也yum删除了预先安装的PHP 5.1。*只是为了确保。但iconv仍在使用glibc版本。

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

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) 

这是一个跨员额从:NullPointer.ph

+0

什么`ldd/usr/lib/httpd/modules/libphp5.so`和`ldd/usr/libexec/httpd/httpd`显示? AFAIK,apache也依赖`libiconv`。你不能在一个进程中加载​​两个版本的`libiconv`。 – 2011-01-20 03:14:03

+0

已更新的问题以反映`ldd/usr/lib/httpd/modules/libphp5.so`。第二个命令给了我一个`没有这样的文件或目录`。 – Randell 2011-01-20 03:24:47

+0

尝试使用`--with-iconv = shared,/ usr/local`配置 – ismail 2011-01-24 08:16:37

回答

9

我刚刚通过手动重新编译php iconv扩展名将php-5.3.3从glibc的iconv更改为GNU libiconv。请按照下列步骤操作:

  1. download php-5.3。3 source code
  2. 提取出来,并进入php-5.3.3/ext/iconv子目录
  3. 执行phpize命令(如果您有没有这样的命令,然后再安装php-devel包)
  4. (*)编辑配置文件(vim configure):在4664行添加iconv_impl_name="" (系统配置确切的行号可以是不同的):

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

现在我跑php -i|grep "iconv impl"并得到了:

iconv implementation => libiconv 

*此招力量配置选择GNU libiconv的,而不是glibc的公司的iconv。默认情况下,它会在第一步检查glibc的iconv,根本不检查GNU libiconv。

-1

我不知道CentOS的,但在基于Debian的发行版,如Ubuntu,你可以选择程序的版本你想要定义/ etc/alternatives中的符号链接。因此,如果您更改symbolink链接/ etc/alternatives/iconv以指向/ usr/local/bin/iconv,则此点应该使用正确的版本。

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

+0

这可能值得一试。我稍后会发布更新。 – Randell 2011-01-26 02:48:20

+5

`/ etc/alternatives`适用于可执行文件,而不是库。 – jilles 2011-01-29 15:10:53

0

你肯定LD_LIBRARY_PATH正确设置为httpd(web服务器)的过程? 如果不行,请尝试将它像:

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

...在启动过程中(即apachectl)的脚本。

您显示的ldd输出看起来正确,但您从用户环境调用ldd,并且httpd的可能会有所不同。

它也可以帮助将PATH设置为“/ usr/local/bin:$ {PATH}”,以防万一。

9

你的模块(libphp5.so)连接到被提供相同的符号(在这种情况下,符号为iconv和库libiconv.so.2和可能libc.so.6)两个共享库。

发生这种情况时,将使用第一个加载的符号:可能libc.so.6libiconv.so.2之前加载,因此它是向您提供iconv符号的那个符号。

您可以强制动态加载器在其他任何之前加载库;您可以通过将LD_PRELOAD环境变量设置为要预加载的库来执行此操作。我不是一个关于Apache的专家,所以我不完全确定它是如何工作的,它是如何启动它的过程以及它使用什么过程的,但我认为在运行apache之前设置LD_PRELOAD应该做到这一点:

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

一个小例子,以显示在动作LD_PRELOAD

将编译myfopen.c作为共享库(myfopen.so):它将提供一个fopen符号(已在libc定义):

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

编译printfopen.c作为可执行(printfopen),其只是打印的fopen的结果;将其链接对阵双方libclibmyfopenLD_LIBRARY_PATH需要让连接器查找图书馆也.):

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

现在我运行它,以测试是否LD_PRELOAD作品:

$ 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 

默认情况下,它在libc之前加载libmyfopen,然后我试图首先强制加载libc,然后libmyfopen

我想你的情况libclibiconv之前被加载,因为前者在加载PHP模块之前由应用程序加载(apache?)。

0

据我所知,这个问题已经回答了,几乎已经死了,但最近我试图找到一种方法来编译PHP与libiconv,因为在PHP中,我无法将“∙”从UTF8转换为CP1251,即使使用iconv //忽视。 但我发现了另一个解决方案,为我工作而无需重新编译(只使用// TRANSLIT):

的iconv( “UTF-8”, “CP1251 // // TRANSLIT忽略”,$文本)

// TRANSLIT将仅音译未知字符(并非全部,因为有些人可能会猜到),所以它会转换俄语'ё',但将未知'∙'音译为0x95(在目标字符集中看起来相同)。

相关问题