использование php в администрировании
Мои отношения с PHP с момента появления PHP3 были двойственными. Я воспринимал его как простой инструмент для решения несложных веб-задач без предварительных упражнений по установке сервера Java или перекомпиляции CGI-скриптов для разных платформ. PHP был (да и остается) простым в изучении и быстрым в развертывании решением, которое уже долгое время вполне соответствует моим запросам.
В один прекрасный день на PHP Website (www.php.net) появилось сообщение о чем-то, называемом “CLI SAPI”. Эта конструкция позволяла использовать парсер PHP без генерирования HTML и не требовала наличия Apache для доставки кода. Вместо этого CLI SAPI, грубо говоря, разрешает открыть файл, определить в нужной строке путь к PHP-парсеру – и вперед к победе. Очень похоже на Perl, Python или bash.
Поначалу я не очень-то доверял подобной технологии. Я использовал PHP для всех своих веб-проектов, одновременно решая администраторские задачи с помощью Perl. Внезапно прекрасные горизонты подернулись тучами...
Однажды я с увлечением потратил кучу времени на составление Perl-скрипта для одной машины только для того, чтобы потом обнаружить, что на ней не установлены требуемые модули Perl. Более того, их инсталляция рисковала доставить массу неприятных проблем – у меня уже был подобный опыт. Но делать было нечего, и я попытался. Через некоторое время CPAN начал ругаться, и вот тут-то я обратил внимание на то, что на этой машине уже установлен PHP, да еще со всеми необходимыми мне дополнениями. Через десять минут мой многострадальный скрипт уже прекрасно работал на PHP.
а нужен ли нам еще один скриптовый язык?
Положа руку на сердце – не нужен. Однако если он уже появился, то в некоторых случаях вполне может быть полезен. Если какой-нибудь
свежеиспеченный язык предлагает ровно такие же возможности, как и уже имеющийся – не вижу причин все бросать и бежать осваивать новинку. С другой стороны, возможность использовать PHP для решения задач администрирования может быть полезной для веб-разработчиков, которые в этом случае смогут отработать свои скрипты на локальной машине без развертывания на ней полномасштабного тестового веб-сервера. Наконец, люди, знакомые с PHP, теперь смогут применять свои навыки и для администрирования своей техники. При другом раскладе им для этого понадобилось бы дополнительно изучать Perl или еще что-нибудь в этом духе, а если надо всего-то переименовать десяток-другой каких-нибудь mp3-шек – то это не самый рациональный путь.
Итак, несмотря на то, что нам, по большому счету, не нужен еще один скриптовый язык, для тех, кто уже разбирается в PHP и не горит желанием тратить свое время на изучение других языков, рассматриваемая технология может стать очень удобным инструментом.
Далее мы рассмотрим несколько простых примеров, которые продемонстрируют использование PHP в новой ипостаси.
первый простой пример
Этот и все последующие примеры максимально упрощены – их смысл состоит в простом показе того, что это работает и работает очень просто. Первый пример – это, собственно тот скрипт, который заставил меня заняться всеми этими исследованиями.
Я составлял скрипт для LDAP и не смог использовать модуль Net::LDAP (его, как вы помните, просто не было на машине). Решить такую задачу с помощью CPAN или Perl – не проблема, однако у меня был только PHP и я использовал именно его. Данный код не повторяет написанный тогда реальный скрипт, но принцип его работы аналогичен.
#!/usr/bin/php -q
$conn=ldap_connect("ldap.linuxlaboratory.org")
or die("Connect failed\n");
$bind = ldap_bind($conn)
or die("Bind failed\n");
$answer = ldap_search($conn, "dc=linuxlaboratory,dc=org", "(sn=Jones)");
$output = ldap_get_entries($conn, $answer);
echo $output["count"]." entries returned\n";
for ($i=0; $i<count($output); $i++) {
if(!isset($output[$i])) break;
echo $output[$i]["dn"]."\n";
}
?>
Если вам уже доводилось работать с PHP, то вы не найдете в этом скрипте ничего сверхъестественного. Я не определял никаких пользовательских функций, все было настроено в инсталлированном PHP. В моем случае это была установка из RPM. На мой взгляд, данный способ удобен, поскольку если я хочу добавить немного LDAP-функциональности, то под Fedora мне достаточно просто выполнить "yum install php-ldap", и все в порядке. SuSe и Mandrake действуют в том же духе. Уверен, что и дебиановский apt-get сработает не хуже.
Первое, что вы, наверное, уже заметили – это аргумент “-q”. Он дает парсеру команду не генерировать HTML-заголовки и вообще не выводить HTML. Второй момент – теги, расположенные до и после секций кода (). Это те же теги, которые используются для выделения PHP-кода в HTML- странице. В данном случае мы отделяем ими код PHP от вывода простого текста. Если вам понадобится вывести на экран большое количество текста, то использовать echo не нужно. Просто закройте секцию PHP, напишите свой текст, а потом откройте новую секцию PHP тегомСкрипт производит простой поиск пользователей с фамилией (sn) “Jones” по указанному ему каталогу LDAP. Массив результатов сохраняется в переменной $output. Внимательный читатель заметит, что $output [“count”] должна быть где-то заранее определена. Функция ldap_get_entries определяет ее в качестве первого ключа в массиве результатов, поскольку у атрибутов LDAP может быть больше одного значения. Вы также можете посмотреть на то, что твориться в массиве без данного ключа, используя для этого функцию count(). Для поиска ошибок можно применить и функцию print_r($arrayname), которая сделает дамп содержимого массива для последующего просмотра. Вот результат работы рассмотренного нами скрипта:
1 entries returned
cn=Brian K Jones (jonesy@linuxlaboratory.org),dc=linuxlaboratory,dc=org
Ну что же, PHP-код дал результат, который вполне можно было ожидать от скрипта на Perl или работы в командной строке.
еще один пример
Второй пример также очень прост. Скрипт, используя одну команду без флагов, должен сообщить мне об открытых на моей машине портах. Для решения этой задачи применим snmpwalk.
#!/usr/bin/php -q
snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
$openports = snmpwalk("localhost", "public", ".1.3.6.1.2.1.6.13.1.3");
foreach($openports as $port)
{
if($port< 1024)
{
$service = getservbyport($port, "tcp");
echo "Port $port: $service\n";
}
}
?>
Здесь работает секретное оружие, о котором знают далеко не все PHP-программисты. Первая строка скрипта вызывает функцию snmp_set_valueretrieval() с заранее определенной константой в качестве аргумента. Без этой строки для того, чтобы пропарсить вывод данных net- snmp, вам бы пришлось написать еще три строчки кода. Но у нас такая строка есть, поэтому вы можете быть уверены в том, что возвращено (и передано getservbyport()) будет только одно значение – значение атрибута в запросе, а не "INTEGER: значение", которое создаст проблемы для getservbyport(), которая ожидает номер порта в форме простого числа.
Вот результат работы этого скрипта, который я назвал “holes.php”:
Port 22: ssh
Port 80: http
Port 199: smux
Port 53: domain
Port 953: rndc
Port 53: domain
Вполне возможно, что такую задачу можно решить и более изящным способом, но приведенный код потребовал на свое написание не более трех минут работы. К чему действительно можно придраться – так это к тому, что скрипт не указывает, с каким интерфейсом он работает – как видите, 53-й порт (DNS) показан дважды (первый – для loopback, а второй – для eth0). Если работать как надо, то надо бы вернуться к данным SNMP и проверить там индекс по какому-нибудь нужному значению. Если работать абы как, то можно конечно вызвать функцию array_unique(), которая выкинет из массива все лишнее, но ведь мы же будем работать на совесть!
заключение
Мне довольно непросто определить аудиторию данной статьи. Хардкорные сисадмины, наверное, сочтут святотатством предложение использовать для администрирования что-либо кроме командной строки или Perl. Веб-программисты, особенно с неважными условиями работы, скорее всего, воспримут это как способ дополнить свои анкеты упоминанием навыков администрирования. Потом придут Python-программисты и скажут, что все это можно сделать двумя строками хорошего Python’а. Здесь есть, что обсудить!
Brian Jones, перевод Алексея Кутовенко.
обсуждение статьи
В один прекрасный день на PHP Website (www.php.net) появилось сообщение о чем-то, называемом “CLI SAPI”. Эта конструкция позволяла использовать парсер PHP без генерирования HTML и не требовала наличия Apache для доставки кода. Вместо этого CLI SAPI, грубо говоря, разрешает открыть файл, определить в нужной строке путь к PHP-парсеру – и вперед к победе. Очень похоже на Perl, Python или bash.
Поначалу я не очень-то доверял подобной технологии. Я использовал PHP для всех своих веб-проектов, одновременно решая администраторские задачи с помощью Perl. Внезапно прекрасные горизонты подернулись тучами...
Однажды я с увлечением потратил кучу времени на составление Perl-скрипта для одной машины только для того, чтобы потом обнаружить, что на ней не установлены требуемые модули Perl. Более того, их инсталляция рисковала доставить массу неприятных проблем – у меня уже был подобный опыт. Но делать было нечего, и я попытался. Через некоторое время CPAN начал ругаться, и вот тут-то я обратил внимание на то, что на этой машине уже установлен PHP, да еще со всеми необходимыми мне дополнениями. Через десять минут мой многострадальный скрипт уже прекрасно работал на PHP.
а нужен ли нам еще один скриптовый язык?
Положа руку на сердце – не нужен. Однако если он уже появился, то в некоторых случаях вполне может быть полезен. Если какой-нибудь
свежеиспеченный язык предлагает ровно такие же возможности, как и уже имеющийся – не вижу причин все бросать и бежать осваивать новинку. С другой стороны, возможность использовать PHP для решения задач администрирования может быть полезной для веб-разработчиков, которые в этом случае смогут отработать свои скрипты на локальной машине без развертывания на ней полномасштабного тестового веб-сервера. Наконец, люди, знакомые с PHP, теперь смогут применять свои навыки и для администрирования своей техники. При другом раскладе им для этого понадобилось бы дополнительно изучать Perl или еще что-нибудь в этом духе, а если надо всего-то переименовать десяток-другой каких-нибудь mp3-шек – то это не самый рациональный путь.
Итак, несмотря на то, что нам, по большому счету, не нужен еще один скриптовый язык, для тех, кто уже разбирается в PHP и не горит желанием тратить свое время на изучение других языков, рассматриваемая технология может стать очень удобным инструментом.
Далее мы рассмотрим несколько простых примеров, которые продемонстрируют использование PHP в новой ипостаси.
первый простой пример
Этот и все последующие примеры максимально упрощены – их смысл состоит в простом показе того, что это работает и работает очень просто. Первый пример – это, собственно тот скрипт, который заставил меня заняться всеми этими исследованиями.
Я составлял скрипт для LDAP и не смог использовать модуль Net::LDAP (его, как вы помните, просто не было на машине). Решить такую задачу с помощью CPAN или Perl – не проблема, однако у меня был только PHP и я использовал именно его. Данный код не повторяет написанный тогда реальный скрипт, но принцип его работы аналогичен.
#!/usr/bin/php -q
$conn=ldap_connect("ldap.linuxlaboratory.org")
or die("Connect failed\n");
$bind = ldap_bind($conn)
or die("Bind failed\n");
$answer = ldap_search($conn, "dc=linuxlaboratory,dc=org", "(sn=Jones)");
$output = ldap_get_entries($conn, $answer);
echo $output["count"]." entries returned\n";
for ($i=0; $i<count($output); $i++) {
if(!isset($output[$i])) break;
echo $output[$i]["dn"]."\n";
}
?>
Если вам уже доводилось работать с PHP, то вы не найдете в этом скрипте ничего сверхъестественного. Я не определял никаких пользовательских функций, все было настроено в инсталлированном PHP. В моем случае это была установка из RPM. На мой взгляд, данный способ удобен, поскольку если я хочу добавить немного LDAP-функциональности, то под Fedora мне достаточно просто выполнить "yum install php-ldap", и все в порядке. SuSe и Mandrake действуют в том же духе. Уверен, что и дебиановский apt-get сработает не хуже.
Первое, что вы, наверное, уже заметили – это аргумент “-q”. Он дает парсеру команду не генерировать HTML-заголовки и вообще не выводить HTML. Второй момент – теги, расположенные до и после секций кода (). Это те же теги, которые используются для выделения PHP-кода в HTML- странице. В данном случае мы отделяем ими код PHP от вывода простого текста. Если вам понадобится вывести на экран большое количество текста, то использовать echo не нужно. Просто закройте секцию PHP, напишите свой текст, а потом откройте новую секцию PHP тегомСкрипт производит простой поиск пользователей с фамилией (sn) “Jones” по указанному ему каталогу LDAP. Массив результатов сохраняется в переменной $output. Внимательный читатель заметит, что $output [“count”] должна быть где-то заранее определена. Функция ldap_get_entries определяет ее в качестве первого ключа в массиве результатов, поскольку у атрибутов LDAP может быть больше одного значения. Вы также можете посмотреть на то, что твориться в массиве без данного ключа, используя для этого функцию count(). Для поиска ошибок можно применить и функцию print_r($arrayname), которая сделает дамп содержимого массива для последующего просмотра. Вот результат работы рассмотренного нами скрипта:
1 entries returned
cn=Brian K Jones (jonesy@linuxlaboratory.org),dc=linuxlaboratory,dc=org
Ну что же, PHP-код дал результат, который вполне можно было ожидать от скрипта на Perl или работы в командной строке.
еще один пример
Второй пример также очень прост. Скрипт, используя одну команду без флагов, должен сообщить мне об открытых на моей машине портах. Для решения этой задачи применим snmpwalk.
#!/usr/bin/php -q
snmp_set_valueretrieval(SNMP_VALUE_PLAIN);
$openports = snmpwalk("localhost", "public", ".1.3.6.1.2.1.6.13.1.3");
foreach($openports as $port)
{
if($port< 1024)
{
$service = getservbyport($port, "tcp");
echo "Port $port: $service\n";
}
}
?>
Здесь работает секретное оружие, о котором знают далеко не все PHP-программисты. Первая строка скрипта вызывает функцию snmp_set_valueretrieval() с заранее определенной константой в качестве аргумента. Без этой строки для того, чтобы пропарсить вывод данных net- snmp, вам бы пришлось написать еще три строчки кода. Но у нас такая строка есть, поэтому вы можете быть уверены в том, что возвращено (и передано getservbyport()) будет только одно значение – значение атрибута в запросе, а не "INTEGER: значение", которое создаст проблемы для getservbyport(), которая ожидает номер порта в форме простого числа.
Вот результат работы этого скрипта, который я назвал “holes.php”:
Port 22: ssh
Port 80: http
Port 199: smux
Port 53: domain
Port 953: rndc
Port 53: domain
Вполне возможно, что такую задачу можно решить и более изящным способом, но приведенный код потребовал на свое написание не более трех минут работы. К чему действительно можно придраться – так это к тому, что скрипт не указывает, с каким интерфейсом он работает – как видите, 53-й порт (DNS) показан дважды (первый – для loopback, а второй – для eth0). Если работать как надо, то надо бы вернуться к данным SNMP и проверить там индекс по какому-нибудь нужному значению. Если работать абы как, то можно конечно вызвать функцию array_unique(), которая выкинет из массива все лишнее, но ведь мы же будем работать на совесть!
заключение
Мне довольно непросто определить аудиторию данной статьи. Хардкорные сисадмины, наверное, сочтут святотатством предложение использовать для администрирования что-либо кроме командной строки или Perl. Веб-программисты, особенно с неважными условиями работы, скорее всего, воспримут это как способ дополнить свои анкеты упоминанием навыков администрирования. Потом придут Python-программисты и скажут, что все это можно сделать двумя строками хорошего Python’а. Здесь есть, что обсудить!
Brian Jones, перевод Алексея Кутовенко.
обсуждение статьи
Сетевые решения. Статья была опубликована в номере 06 за 2005 год в рубрике sysadmin