Как включить расширение PHP OCI8, используя Oracle Instant Client, в Ubuntu 18.04 LTS с PHP-FPM и NGINX?

Я использую последние пакеты PHP, доступные из https://launchpad.net/~ondrej/+archive/ubuntu/php .

Когда я собираю и устанавливаю расширение OCI8, кажется, что все в порядке, но, несмотря на включение расширения в конфигурации PHP-FPM, его присутствие не отражается в выводе из phpinfo(),

В следующем Gist подробно описан процесс, который я использую для настройки, сборки и установки расширения OCI8 PHP:

https://gist.github.com/cbj4074/fa761f60b6f8db431539d76ebfba828e

Тот же самый процесс и конфигурация прекрасно работают в Ubuntu 16.04 LTS, поэтому кажется, что в Ubuntu 18.04 LTS есть принципиальное отличие, будь то операционная система или рассматриваемые пакеты PHP.

В качестве важной (и я подозреваю, относящейся к этой проблеме) справочной информации в Ubuntu 18.04 LTS расширение не загружается в среде CLI «из коробки» с ошибкой:

Предупреждение PHP: Запуск PHP: невозможно загрузить динамическую библиотеку ‘/usr/lib/php/20160303/oci8.so’ — libmql1.so: не удается открыть файл общего объекта: такого файла или каталога в «Неизвестно» в строке 0 нет.

Я решил проблему следующим образом:

# echo 'LD_LIBRARY_PATH="/opt/oracle/instantclient_12_2"' >> /etc/environment

Я думал, что, возможно, добавление LD_LIBRARY_PATH к конфигурации среды PHP-FPM может решить аналогичную проблему там:

# echo "env['LD_LIBRARY_PATH'] = /opt/oracle/instantclient_12_2" >> /etc/php/7.2/fpm/pool.d/www.conf
# systemctl restart php7.2-fpm

Это действительно вызывает LD_LIBRARY_PATH значение, как указано, должно быть отражено как в Environment раздел phpinfo() (при отображении через PHP-FPM + NGINX и запросе из браузера) и PHP Variables раздел, как $_SERVER['LD_LIBRARY_PATH'],

Как ни странно, даже если в PHP-FPM ведение журнала установлено на debugЯ не вижу никаких следов libmql1.so ошибка, которую я испытываю с CLI. Расширение OCI8 просто не загружается, молча. display_startup_errors = On в PHP-FPM эффективен php.ini, тоже.

Я решил посмотреть, работает ли расширение OCI8 в Apache, на том же сервере, и работает, если я добавлю export LD_LIBRARY_PATH=/opt/oracle/instantclient_12_2 в /etc/apache2/envvars; в отсутствие Apache жалуется на запуск:

Предупреждение PHP: Запуск PHP: не удается загрузить динамическую библиотеку ‘oci8.so’ (пробовал: /usr/lib/php/20170718/oci8.so (libmql1.so: невозможно открыть общий объектный файл: такого файла или каталога нет), / usr / lib / php / 20170718 / oci8.so.so (/usr/lib/php/20170718/oci8.so.so: не удается открыть общий объектный файл: такой файл или каталог отсутствуют)) в поле «Неизвестно» в строке 0

Ни одно из этого дела с LD_LIBRARY_PATH необходим на Ubuntu 16.04 LTS и основан на моих наблюдениях и комментариях относительно https://stackoverflow.com/a/45242468/1772379 , что изменилось в Ubuntu 17.10 и Ubuntu 18.04 LTS.

Кто-нибудь еще пробовал это, особенно на Ubuntu 18.04 LTS?

Я пробовал это на двух разных Vagrant VM, laravel/homestead поле 6.0.0 и ubuntu/bionic64 box v20180509.0.0, и поведение одинаково в обоих.

Любые другие идеи будут наиболее ценными!

РЕДАКТИРОВАТЬ 1:

Я спросил об этой проблеме на GitHub-трекере сопровождающего пакета и он предположил, что проблема связана с неспособностью установить соответствующий RPATH во время компиляции.

Я объясняю в своем ответе, что я я установить соответствующее значение, но проблема остается закрытой.

Однако я замечаю интересную деталь, заключающуюся в том, что скомпилированное расширение в Ubuntu 18.04 использует RUNPATH (и не RPATH, который используется в Ubuntu 16.04). Если PHP-FPM игнорирует RUNPATHи ищет только RPATH, это объяснило бы это поведение.

РЕДАКТИРОВАТЬ 2:

Этот еще открытый отчет выглядит как отличный кандидат для представления наблюдаемого поведения:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=859732

(обнаружен в комментариях к использовать RPATH, но не RUNPATH? )

РЕДАКТИРОВАТЬ 3:

По совету комментатора я пересмотрел обновление ld Конфигурация перед созданием расширения, и это решило проблему! Я пробовал это раньше, но, должно быть, пропустил что-то между попытками сборки:

# echo /opt/oracle/instantclient_12_2 > /etc/ld.so.conf.d/oracle-instantclient.conf
# ldconfig

Я до сих пор не знаю почему LD_LIBRARY_PATH в этом случае не работает должным образом, но, кроме того, добавление пути к библиотеке Instant Client в конфигурацию компоновщика кажется более подходящим.

РЕДАКТИРОВАТЬ 4:

Я сказал в моем предыдущем редактировании, что изменение ldconfig представляет собой лучший подход, но пришел к выводу (по доброму совету комментатора), что это может привести к нежелательным конфликтам библиотек, потому что эффекты являются общесистемными.

Оглядываясь назад, имеет смысл минимизировать «побочный ущерб» от модификаций связей библиотеки времени выполнения, ограничивая их средой исполнения через LD_LIBRARY_PATH, Соответственно, я мотивирован, чтобы определить, почему это не работает на Ubuntu 18.04 LTS.

Я чувствую, что окончательно установил, что демон PHP-FPM игнорирует LD_LIBRARY_PATH на Ubuntu (и имеет, по крайней мере, Ubuntu 16.04 LTS; см. Комментарии для объяснения).

ld.so(8) Состояния man-страницы (в зависимости от порядка поиска путей к библиотекам времени выполнения):

Использование переменной среды LD_LIBRARY_PATH (если исполняемый файл не запущен в режиме безопасного выполнения; см. Ниже). [так] в этом случае это игнорируется.

Пока я не могу придумать ни одной другой причины, по которой этот путь был бы проигнорирован. из secure-execution modeВ том же документе говорится:

 Secure-execution mode
For  security reasons, the effects of some environment variables are voided or modified if the dynamic linker determines that the binary
should be run in secure-execution mode.  (For details, see the discussion of individual environment variables below.)  A binary is  exe‐
cuted  in  secure-execution  mode if the AT_SECURE entry in the auxiliary vector (see getauxval(3)) has a nonzero value.  This entry may
have a nonzero value for various reasons, including:

*  The process's real and effective user IDs differ, or the real and effective group IDs differ.  This typically occurs as a  result  of
executing a set-user-ID or set-group-ID program.

*  A process with a non-root user ID executed a binary that conferred capabilities to the process.

*  A nonzero value may have been set by a Linux Security Module.

Во-первых, режим безопасного выполнения, похоже, не действует, так как исполняемые файлы PHP не имеют этого флага (AT_SECURE является 0):

LD_SHOW_AUXV=1 /usr/sbin/php-fpm7.1 -daemonize --fpm-config /etc/php/7.1/fpm/php-fpm.conf
AT_SYSINFO_EHDR: 0x7ffc569e1000
AT_HWCAP:        178bfbff
AT_PAGESZ:       4096
AT_CLKTCK:       100
AT_PHDR:         0x55ceab0c4040
AT_PHENT:        56
AT_PHNUM:        9
AT_BASE:         0x7f823c77f000
AT_FLAGS:        0x0
AT_ENTRY:        0x55ceab19e360
AT_UID:          0
AT_EUID:         0
AT_GID:          0
AT_EGID:         0
AT_SECURE:       0
AT_RANDOM:       0x7ffc56962349
AT_HWCAP2:       0x0
AT_EXECFN:       /usr/sbin/php-fpm7.1
AT_PLATFORM:     x86_64

Мне пришло в голову, что процессы дочернего пула FPM могут демонстрировать разные AT_SECURE значения, но выходные данные идентичны для самого демона PHP-FPM, а также для любых дочерних процессов. Родитель и дочерние элементы имеют следующие значения:

# od -t d8 /proc/851/auxv
0000000                   33      140722944548864
0000020                   16            395049983
0000040                    6                 4096
0000060                   17                  100
0000100                    3       93903778242624
0000120                    4                   56
0000140                    5                    9
0000160                    7      140365152313344
0000200                    8                    0
0000220                    9       93903779136352
0000240                   11                    0
0000260                   12                    0
0000300                   13                    0
0000320                   14                    0
0000340                   23                    0
0000360                   25      140722944193929
0000400                   26                    0
0000420                   31      140722944196579
0000440                   15      140722944193945
0000460                    0                    0

Во-вторых, ни одна из этих причин, кажется, не применима, учитывая следующее:

1) Нет никаких признаков того, что PHP-FPM или его дочерние процессы имеют реальные и эффективные идентификаторы пользователей или групп, которые отличаются (благодаря https://unix.stackexchange.com/a/202359 для этой команды):

# ps -e -o user= -o ruser= | awk '$1 != $2'
systemd+ systemd-timesync
systemd+ systemd-resolve
beansta+ beanstalkd
message+ messagebus
daemon   root
systemd+ systemd-network

# ps -e -o group= -o rgroup= | awk '$1 != $2'
systemd+ systemd-timesync
systemd+ systemd-resolve
beansta+ beanstalkd
message+ messagebus
daemon   root
systemd+ systemd-network

2) У рассматриваемых двоичных файлов нет никаких возможностей (следующие команды не выводят):

# getcap /usr/lib/php/20170718/oci8.so
# getcap -r /opt/oracle/instantclient_12_2/

3) Я убедился, что AppArmor отключен (у него нет политики, которая должна влиять на PHP-FPM, в любом случае):

# systemctl disable apparmor
Synchronizing state of apparmor.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable apparmor
# reboot
# aa-status
apparmor module is loaded.
0 profiles are loaded.
0 profiles are in enforce mode.
0 profiles are in complain mode.
0 processes have profiles defined.
0 processes are in enforce mode.
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.

Итак, почему PHP-FPM игнорирует LD_LIBRARY_PATHесли не по какой-либо из вышеперечисленных причин?

РЕДАКТИРОВАТЬ 5 (Решение):

Проницательный комментатор, @ vinc17, указывает, что в системах, работающих systemdпеременные среды, такие как LD_LIBRARY_PATH, не обязательно распространяются на процессы, которые запускаются через systemd Блок.

Другими словами, PHP-FPM не «игнорирует» LD_LIBRARY_PATHскорее это не передается процессу. И попытки установить LD_LIBRARY_PATH в конфигурации PHP-FPM бесполезно, потому что уже слишком поздно что-либо делать со значением.

По этому совету мне пришло в голову установить LD_LIBRARY_PATH в systemd контекст, а именно, в файле (файлах) модуля, который запускает демон (ы) PHP-FPM, и в этом случае PHP-FPM успешно загружает расширение OCI8.

Само собой разумеется, мы хотим избежать редактирования файла сопровождающего пакета (чтобы избежать конфликтов во время будущих обновлений), поэтому мы расширяем его:

# mkdir /etc/systemd/system/php7.1-fpm.service.d
# touch /etc/systemd/system/php7.1-fpm.service.d/environment.conf

К этому файлу мы добавляем следующее:

[Service]
Environment=LD_LIBRARY_PATH=/opt/oracle/instantclient_12_2

И сделать изменения эффективными:

# systemctl daemon-reload
# systemctl restart php7.1-fpm

Для более полного примера, который касается нескольких совместно установленных версий PHP, смотрите мой пост на https://github.com/oerdnj/deb.sury.org/issues/865#issuecomment-395441936 .

5

Решение

Первый, Ошибка Debian 859732 это совершенно другая проблема (я бы даже сказал противоположную проблему): для этой ошибки несколько версий библиотеки присутствуют в пути поиска (одна в некотором каталоге, указанном LD_LIBRARY_PATH и другой в некотором каталоге, указанном в пути выполнения), но динамический компоновщик выбрал неправильный.

В вашем случае проблема в том, что запрошенная библиотека не найдена нигде в пути поиска. Также обратите внимание, что в вашем случае это PHP пытается открыть библиотеку (через dlopen?), так как сообщение начинается с «PHP Warning:». Однако, похоже, что механизмы такие же, как и при обычном динамическом связывании.

После установки библиотеки вам нужно как минимум одно из:

  • Ничего особенного, если библиотека была установлена ​​в каталог, который ищется по умолчанию. Так как вы получаете ошибку, это не ваш случай.
  • Предоставление каталога в пути выполнения, который должен быть указан во время компиляции программного обеспечения, которому потребуется библиотека. Проблема в том, что в Linux это не делается стандартными средствами сборки, и может быть сложно сделать это правильно, не нарушая другие вещи. Однако в контексте dlopenпрограммное обеспечение (здесь, PHP), возможно, настроило то, что можно назвать «путем поиска плагинов», куда вы можете поместить свои библиотеки.
  • Предоставление каталога в LD_LIBRARY_PATH, Это то, что вы пытались, но ваш LD_LIBRARY_PATH кажется неверным. Библиотеки обычно устанавливаются в подкаталогах с именем lib (или же lib32 или же lib64 в особых случаях). Так, export LD_LIBRARY_PATH=/opt/oracle/instantclient_12_2 кажется неправильно. Поиск полного пути к библиотеке oci8.soи просто взять часть каталога этого пути для LD_LIBRARY_PATH,

Замечания: strace может быть полезно посмотреть, какие каталоги считаются для поиска библиотек. РЕДАКТИРОВАТЬ: ldd а также objdump -p другие полезные инструменты, чтобы найти, что происходит с путями поиска.

РЕДАКТИРОВАТЬ 2: Еще один момент, который следует отметить при выборе пути запуска, заключается в том, что косвенные зависимости библиотеки обнаруживаются при RPATH используется, но не когда RUNPATH используется (так, в этом последнем случае все зависимости также необходимо иметь путь запуска, если они зависят от других библиотек, чтобы можно было найти все библиотеки, не прибегая к LD_LIBRARY_PATH). Это описано в последних версиях справочной страницы ld.so (8):

Используя каталоги, указанные в DT_RUNPATH атрибут динамического раздела двоичного файла, если он есть. Такие каталоги ищутся только для поиска тех объектов, которые требуются DT_NEEDED (прямые зависимости) и не относятся к дочерним объектам тех объектов, которые сами должны иметь свои собственные DT_RUNPATH записей. Это непохоже DT_RPATH, который применяется для поиска всех дочерних элементов в дереве зависимостей.

Наверное, поэтому без использования LD_LIBRARY_PATHэто работало с 16.04 (где RPATH используется) но не с 18.04 (где RUNPATH используется).

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]