вторник, 23 декабря 2008 г.

Получение списка загруженных модулей сервера на Apache 1 из PHP

Думаю, что многие из вас сталкивались с работой с модулями сервера Apache на PHP. Всегда перед началом использования какого-либо серверного модуля необходимо проверить его активность и доступность. Как оказалось, определение загруженных модулей Apache средствами PHP может стать реальной проблемой, с чем я и столкнулся, потратил уйму времени, чтобы придумать решение.

Итак, обо всём по порядку. В PHP есть специализированная функция apache_get_modules(), работает она на PHP 4 >= 4.3.2, PHP 5. Эта функция позволяет получить список загруженных Apache модулей. Конечно, она идеально подходит для этой задачи. Так думал и я, пока не наступил на «грабли совместимости». Как написано в ChangeLog, функция apache_get_modules() с версии 5.0.0 стала доступна в Apache 1, и в PHP Apache 2 filter API. До того, она была доступна лишь при использовании Apache 2 handler API. Но, как показали тесты на разных серверах, – функция не оправдала надежды, она просто отсутствовала в Apache меньше версии 2.

Поставленная задача требовала максимальной совместимости разрабатываемого PHP продукта со всеми Apache серверами, начиная с версии 1.3. Поэтому я продолжил поиски решения. Функция phpinfo() выводит довольно много системной и серверной информации не только о сборке PHP, но и об остальных подключенных модулях и библиотеках. Решил воспользоваться этим шансом. Написал простой парсер для информации выводимой phpinfo(), который разбирал информацию из пункта Loaded Modules раздела apache2handler, если это был Apache 2. Или если это был Apache младше 2-й версии, то искал информацию о подключенных модулях в разделе Environment. Это решение, аналогично, успешно работало только на Apache 2, а на остальных сервер не выводил информацию о всех загруженных модулях, а только о тех, что были скомпилированы на этапе сборки.

Два выше расписанных метода определения не давали мне должной совместимости со всеми серверами и сборками. Я перекопал много информации, чтобы найти способ определения loaded Apache modules средствами простого PHP скрипта, но так и не смог найти готового решения.

Раз нельзя определить средствами PHP, какие из модулей сервера загружены, тогда надо заставить сам Apache передавать эту информацию в исполняемый скрипт. Простейший метод реализации, что мне пришёл в голову, это написать .htaccess скприпт, который бы, при исполнении PHP скрипта, передавал в него список загруженных модулей. Список можно передать в качестве $_GET параметра.

В конфигурационном файле .htaccess есть возможность использовать условную директиву . Она проверяет, если подключен указанный модуль Apache, то исполняет ветку, заключённую между директивами. Допускается использование и вложенных директив.

Для передачи дополнительных параметров PHP скрипту, с сохранением его оригинальных GET параметров, нужен как минимум загруженный модуль mod_rewrite. Он будет производить перехват запроса, добавлять необходимые параметры, если модуль активен, и отдавать его обратно в сприпт. Файл .htaccess даёт возможность объявлять переменные окружения и задавать им значения при помощи ключа [E], который мы добавим в RewriteRule.

Приведу фрагмент .htaccess, который написал:

Order deny,allow
allow from all

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [E=MOD_REWRITE_ENABLED:mod_rewrite]
<IfModule mod_env.c>
RewriteRule .* - [E=MOD_ENV_ENABLED:|mod_env]
</IfModule>
<IfModule mod_auth_basic.c>
RewriteRule .* - [E=MOD_AUTH_BASIC_ENABLED:|mod_auth]
</IfModule>
<IfModule mod_proxy.c>
RewriteRule .* - [E=MOD_PROXY_ENABLED:|mod_proxy]
</IfModule>
RewriteRule ^index\.php$ index2.php?modules=%{ENV:MOD_REWRITE_ENABLED}%{ENV:MOD_ENV_ENABLED}​%{ENV:MOD_AUTH_BASIC_ENABLED}%{ENV:MOD_PROXY_ENABLED} [QSA,L]
</IfModule>

Этот файл необходимо положить в одну директорию с файлом index.php. Htaccess перехватит исполнение скрипта index.php. В зависимости от загруженных модулей выставит переменные окружения. Сервер добавит их конкатенацию в качестве переменной $_GET['modules'] к остальным параметрам GET запроса и запустит PHP скрипт на исполнение.

Разобрать строчку modules не составит труда, для этого используем функцию explode("|", $_GET['modules']). В результате получим уже готовый массив с именами загруженных модулей Apache.

Приведенный выше пример .htaccess рассчитан на определение только четырёх модулей Apache: mod_rewrite, mod_env, mod_auth_basic и mod_proxy. Вы довольно легко можете его расширить на любое количество необходимых модулей путём добавления дополнительных директив для проверок. В любом случае, вы ничего не теряете, даже если не загружен основной модуль mod_rewrite.c. Тогда лишь не отработает перенаправление и не будет передан параметр $_GET['modules']).

Надеюсь, вы не потратите столько времени, сколько потратил я, на решение такой, несложной, на первый взгляд, задачи, как детектирование модулей Apache средствами PHP. Если кто-то сталкивался с такой проблемой и смог придумать более оптимальное решение, как это сделать на версии сервера младше Apache 2, то внимательно вас выслушаю.

Комментариев нет:

Отправить комментарий

Рекоммендую

Попробуйте надёжный хостинг от Scala Hosting