Я использую последние доступные пакеты 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 * нет 1018 *
Я решил проблему следующим образом:
# 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, laravel/homestead
box 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.04LTS; см. Комментарии для объяснения).
Состояние man-страницы ld.so(8)
(в зависимости от порядка поиска путей к библиотекам времени выполнения):
Использование переменной среды LD_LIBRARY_PATH (если исполняемый файл не запущен в режиме безопасного выполнения (см. ниже).[sic] в этом случае он игнорируется.
Пока что я не могу придумать ни одной другой причины, по которой путь будет игнорироваться.Из 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
Unit.
Другими словами,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.