10

私が取り組んでいるコードは、Windows XP と Mac OS X で完全に動作します。CentOS (および Fedora と Ubuntu) でテストすると、正しく動作しません。ネットを検索した結果、問題を引き起こしているのは のglibcバージョンであるという結論に達しました。そのため、Zend Lucene が適切に動作するためには のバージョンがiconv必要です。libiconviconv

私はすでに libiconv をダウンロードし、それを , で構成しましたが、--prefix=/usr/localエラーは発生しませんでした。実行するとバージョンが. 単純なバージョンはまだ提供されていますが。makemake install/usr/local/bin/iconv --versionlibiconviconv --versionglibc

次に、を使用してソースから PHP を再コンパイルし--with-iconv=/usr/localました。それでも、は使用中のバージョンphpinfo()を示しています。また、を使用または使用して、他のいくつかのコンパイルも既に試しました。iconvglibc--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 を示しています。また、念のため、プリインストールされている PHP 5.1.* を yum で削除しました。しかし、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

4

5 に答える 5

10

モジュール(libphp5.so)は、同じシンボルを提供している2つの共有ライブラリにリンクされています(この場合、シンボルはiconvであり、ライブラリはlibiconv.so.2であり、おそらくlibc.so.6)。

これが発生すると、最初にロードされたシンボルが使用されます。おそらくlibc.so.6前にロードされるため、シンボルlibiconv.so.2を提供するiconvシンボルになります。

ダイナミックローダーに他のどのライブラリよりも先にライブラリをロードさせることができます。これを行うには、LD_PRELOAD環境変数をプリロードするライブラリに設定します。

私はApacheの専門家ではないので、Apacheがどのように機能するか、どのようにプロセスを開始するか、どのプロセスを使用するかについては完全にはわかりLD_PRELOADませんが、apacheを実行する前に設定することでうまくいくと思います。

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の実行可能ファイル()としてコンパイルします。との両方に対してリンクします(リンカーがライブラリを検索できるようにするために必要です):printfopenfopenlibclibmyfopenLD_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

デフォルトでは、のlibmyfopen前にロードしlibc、次に強制的にロードしてから最初にロードしようとしましlibclibmyfopen

あなたの場合、前者はPHPモジュールをロードする前にアプリケーション(apache?)によってロードされるため、以前にロードされているlibcと思います。libiconv

于 2011-01-30T15:13:04.907 に答える
10

php-5.3.3 を glibc の iconv から GNU libiconv に変更したところ、php iconv 拡張機能を手動で再コンパイルしました。次の手順を実行します:

  1. php-5.3.3ソースコードパッケージをダウンロード
  2. それを抽出してphp-5.3.3/ext/iconvサブディレクトリに移動します
  3. コマンドを実行しphpizeます(そのようなコマンドがない場合は、php-develパッケージをインストールします)
  4. (*) 構成ファイルの編集 ( vim configure): iconv_impl_name=""4664 行に追加 (システム構成の正確な行番号は異なる場合があります):

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

* このトリックにより、configure は glibc の iconv ではなく GNU libiconv を選択するようになります。デフォルトでは、最初のステップで glibc の iconv をチェックし、GNU libiconv をまったくチェックしません。

于 2011-01-31T12:50:46.243 に答える
0

LD_LIBRARY_PATHhttpd (Web サーバー) プロセスに対して適切に設定されていますか? そうでない場合は、次のように設定してみてください。

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

...プロセスを開始するスクリプト(つまりapachectl)。

あなたが示したldd出力は正しいように見えますが、lddユーザーの環境から呼び出したため、httpd は異なる可能性があります。

念のため、PATH を「/usr/local/bin:${PATH}」に設定することも役立ちます。

于 2011-01-29T01:49:00.930 に答える
-1

CentOS についてはわかりませんが、Ubuntu などの debian ベースのディストリビューションでは、起動するプログラムのバージョンを選択して、/etc/alternatives でシンボリック リンクを定義できます。

そのため、/usr/local/bin/iconv を指すようにシンボリック リンク /etc/alternatives/iconv を変更すると、この時点から正しいバージョンが使用されます。

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

于 2011-01-25T16:44:45.187 に答える