Как заставить PHP использовать версию iconv для libiconv вместо установленной CentOS версии glibc? - PullRequest
9 голосов
/ 20 января 2011

Код, над которым я работаю, прекрасно работает в Windows XP и Mac OS X. При тестировании его на CentOS (и в Fedora и Ubuntu) он не работает должным образом.Поиск в сетях привел меня к выводу, что проблема заключается в glibc версии iconv.Так что теперь мне нужна libiconv версия iconv для Zend Lucene для правильной работы.

Я уже скачал libiconv и настроил его на --prefix=/usr/local, make, затем make install без каких-либо ошибок.Кажется, что он был успешно установлен, потому что выполнение /usr/local/bin/iconv --version говорит, что версия - libiconv.Хотя простой iconv --version по-прежнему дает версию glibc.

Затем я перекомпилировал PHP из исходного кода, используя --with-iconv=/usr/local.Но все же, phpinfo() показывает, что используется iconv версия glibc.Я также уже пробовал несколько других компиляций, используя --with-iconv-dir или /usr/local/bin/php.

Конечно, я перезапустил веб-сервер после перекомпиляции PHP.

У меня есть следующая строка в моем/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. *, Чтобы убедиться.Но 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

Ответы [ 5 ]

9 голосов
/ 31 января 2011

Я только что изменил свой php-5.3.3 с glibc iconv на GNU libiconv через ручную перекомпиляцию расширения php iconv.Выполните следующие действия:

  1. загрузите php-5.3.3 исходный код пакет
  2. извлеките его и перейдите в php-5.3.3/ext/iconv подкаталог
  3. executeКоманда 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

* Этот трюк заставляет сконфигурировать выбор GNU libiconv вместо glibc's iconv,По умолчанию он проверяет glibc iconv на первом этапе и вообще не проверяет GNU libiconv.

9 голосов
/ 30 января 2011

Ваш модуль (libphp5.so) связан с двумя общими библиотеками, которые предоставляют один и тот же символ (в данном случае символ iconv, а библиотеки libiconv.so.2 и, вероятно, libc.so.6).

Когда это происходит, используется первый загруженный символ: вероятно, libc.so.6 загружается раньше, чем libiconv.so.2, и, следовательно, именно он предоставляет вам символ iconv.

Вы можете заставить динамический загрузчик загружать библиотеку перед любой другой; Вы можете сделать это, установив переменную окружения LD_PRELOAD в библиотеку, которую вы хотите предварительно загрузить.

Я не эксперт по 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 в виде исполняемого файла (printfopen), который просто печатает результат fopen; свяжет его как с libc, так и с libmyfopen (необходимо LD_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, затем я попытался принудительно загрузить libc, а затем libmyfopen.

Я полагаю, что в вашем случае libc загружается до libiconv, поскольку первый загружается приложением (apache?) До загрузки модуля PHP.

0 голосов
/ 26 марта 2015

Я понимаю, что на этот вопрос уже дан ответ и он почти мертв, но недавно я попытался найти способ скомпилировать PHP с помощью libiconv, потому что в PHP я не мог преобразовать "∙" из UTF8 в CP1251 даже с помощью iconv // IGNORE,Но я нашел другое решение, которое работало для меня без перекомпиляции (просто используйте // TRANSLIT):

iconv ("UTF8", "CP1251 // TRANSLIT // IGNORE", $ text)

// TRANSLIT транслитерует ТОЛЬКО неизвестные символы (не все, как некоторые могут догадаться), поэтому он преобразует русский 'ё', но транслитерует неизвестные '∙' в 0x95 (который выглядит так же в целевой кодировке).

0 голосов
/ 29 января 2011

Вы уверены, что LD_LIBRARY_PATH настроен правильно для процесса httpd (веб-сервер)?Если нет, попробуйте установить его следующим образом:

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

... в скрипте, который запускает процесс (т. Е. apachectl).

Вывод ldd, который вы показали, выглядит правильно,но вы вызвали ldd из среды пользователя, и httpd может отличаться.

На всякий случай может также помочь установить PATH в "/ usr / local / bin: $ {PATH}".

0 голосов
/ 25 января 2011

Я не знаю о CentOS, но в дистрибутивах на основе Debian, таких как Ubuntu, вы можете выбрать версию программы, для которой вы хотите определить символические ссылки, в /etc/alternatives.

Итак,если вы измените ссылку на символьную ссылку / etc / alternatives / iconv, чтобы указать на / usr / local / bin / iconv, то на этом этапе она должна использовать правильную версию.

http://www.debian -администрация.org / статьи / 91

...