2011-01-20 69 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(在目標字符集中看起來相同)。

相關問題