Как заставить PHP использовать libiconv версию iconv вместо установленной версии CentOS, установленной на CentOS?

Код, над которым я работаю, отлично работает в 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

Я только что изменил свой php-5.3.3 с иконки glibc на 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 выбирать GNU libiconv вместо значка glibc. По умолчанию он проверяет значок glibc на первом шаге и вообще не проверяет GNU libiconv.

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

Когда это произойдет, используется первый загруженный символ: возможно, libc.so.6 загружается до libiconv.so.2 и, таким образом, он предоставляет вам 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.

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

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

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

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

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

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

iconv («UTF8», «CP1251 // TRANSLIT // IGNORE», $ text)

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

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

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

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