Ubuntu предоставляет в комплекте с пакетом apache2 утилиты для включения\выключения виртуальных хостов и модулей. Однако, создание конфигов для виртуальных хостов отнимают дополнительное время. Поэтому, мне захотелось исправить этот недостаток. Можно было, конечно, сделать автоматические поддомены для апача, но я решил написать скрипт, который создает файлы конфигурации виртуальных хостов для апача, а так же, при необходимости, добавляет имя хоста в файл /etc/hosts. Я не очень хорошо пишу скрипты в bash’e, поэтому решил использовать PHP для моей довольно простой задачи, который я, к тому же, знаю довольно неплохо.
Итак, в этой статье мы сделаем сразу две полезных вещи: ознакомимся с операциями ввода\вывода командной строки в PHP и напишем скрипт, который совсем немного упростит нам жизнь.
Проверка прав доступа
Наверное, ни для кого не секрет, что достаточно просто в первой строке PHP скрипта написать
#!/usr/bin/env php
и такой скрипт можно будет выполнить как обычную программу в Linux.
Прежде всего, нам нужно проверить, есть ли у нас право на запись в ту самую папку, которая содержит в себе конфиги виртуальных хостов, а обычно для этого нужны root права. Проверить это довольно просто:
- $virtual_hosts_dir = “/etc/apache2/sites-available/”;
 - if (!is_dir($virtual_hosts_dir) || !is_writable($virtual_hosts_dir))
 - {
 - echo “You must run this script as root!\n“;
 - exit;
 - }
 
Получение информации из параметров
Далее, нам необходимо узнать у пользователя некоторую информацию, которая нам нужна для создания конфига. Кроме последовательного ввода из консоли, можно передать эту информацию в качестве параметров, которые мы передаем при вызове скрипта. В PHP есть глобальные переменные $argc и $argv. Первая содержит количество входящих параметров, а вторая — массив со входящими параметрами. По-умолчанию входящий параметр всего один — полный путь к вызываемому скрипту. Таким образом, обработка входящих переменных сводится просто к обработке массива:
- if ($argc>1)
 - {
 - for ($i=1; $i<$argc; $i++)
 - {
 - $option = explode(“=”, $argv[$i]);
 - switch ($option[0])
 - {
 - case “-h”:
 - case “–add-to-hosts”:
 - $add_to_hosts = true;
 - break;
 - case “-n”:
 - case “–no-add-to-hosts”:
 - $add_to_hosts = false;
 - break;
 - case “-a”:
 - case “–server-alias”:
 - if (isset($option[1]))
 - {
 - $server_alias = $option[1];
 - }
 - else
 - {
 - echo “Wrong option: {$argv[$i]}\n“;
 - }
 - break;
 - case “-d”:
 - case “–document-root”:
 - if (isset($option[1]))
 - {
 - if ($option[1] == “default”)
 - {
 - $document_root = $default_doc_root
 - }
 - else if (is_dir(dirname($option[1])))
 - {
 - $document_root = $option[1];
 - }
 - }
 - else
 - {
 - echo “Wrong option: {$argv[$i]}\n“;
 - }
 - break;
 - default:
 - if (substr($argv[$i], 1, 1) == ‘-‘)
 - {
 - echo “Unknown option: {$argv[$i]}\n“;
 - }
 - break;
 - }
 - }
 - }
 
Потоки ввода\вывода
Но не всегда ведь удобно вбивать кучу параметров в консоль. Поэтому теперь мы просим пользователя ввести с клавиатуры то, что нам до сих пор неизвестно. Для этого нам понадобятся потоки ввода\вывода, а в данном случае только ввода. В PHP для работы с потоками ввода\вывода используются константы STDIN, STDOUT, STDERR. По сути, эти потоки ничем не отличаются от файловых потоков и работать с ними так же просто. Например, строка:
- $line = fgets(STDIN);
 
просто считает строку из консоли и запишет её в переменную $line. В данном случае, мы не открывали и не закрывали поток, т.к. PHP делает это автоматически. Но, мы можем открыть поток вручную и держать его открытым столько, сколько нам нужно. Это будет работать быстрее, если Вам нужно считать\записать более одной строки:
- $stdin = fopen(“php://stdin”, “r”);
 - $line1 = gets($stdin);
 - $line2 = gets($stdin);
 - fclose($stdin);
 
В данном случае мы сначала открываем поток, считываем из него две строки и закрываем его.
С записью аналогично, хотя я предпочитаю для вывода на экран просто использовать echo.
Продолжаем писать наш скрипт. Пока у нас нет хоть какой-то строки в качестве имени хоста, продолжаем просить пользователя, чтобы он что-то ввел:
- while (!$server_alias)
 - {
 - echo “Enter your hostname: “;
 - $server_alias = trim(fgets(STDIN));
 - }
 
Теперь, спросим у пользователя, нужно ли добавлять информацию о этом хосте в /etc/hosts, но спрашиваем только в том случае, если эта информация не была передана в качестве параметра. Так как скрипт я писал себе для повседневной работы, то никаких реальных сайтов у меня не будет и чаще всего нужно будет добавлять хост в /etc/hosts, поэтому если мы ничего не вводим, а просто нажимаем Enter то это принимается как согласие:
- if ($add_to_hosts === null)
 - {
 - echo “Add $server_alias to your /etc/hosts ? (Y/N) [Y]: “;
 - $line = trim(fgets(STDIN));
 - if ($line == ‘n’ || $line == ‘N’)
 - {
 - $add_to_hosts = false;
 - }
 - else
 - {
 - $add_to_hosts = true;
 - }
 - }
 
То же самое и с корневой директорией сайта:
- if (!$document_root)
 - {
 - $default_doc_root = $default_doc_root.‘/’.$server_alias;
 - echo “Enter your document root [$default_doc_root]: “;
 - $line = trim(fgets(STDIN));
 - if ($line && is_dir(dirname($line)))
 - {
 - $document_root = $line;
 - }
 - else
 - {
 - $document_root = $default_doc_root;
 - }
 - }
 
Генерация конфиг-файла
На этом этапе весь сбор информации закончен и у нас есть все, что нужно, для того, чтобы создать конфиг. Надо убедится, что корневая директория сайта существует, а если её нет — создадим её:
- if (!is_dir($document_root))
 - {
 - mkdir($document_root);
 - }
 
Мы спрашивали у пользователя по поводу добавления хоста в /etc/hosts. Сделаем это, если он согласился:
- if ($add_to_hosts)
 - {
 - $hosts = file_get_contents(“/etc/hosts”);
 - $hosts .= “127.0.0.1\t$server_alias\n“;
 - file_put_contents(“/etc/hosts”, $hosts);
 - }
 
Собственно так выглядит шаблон нашего конфига:
- $host_template = <<<HOST
 - <VirtualHost *:80>
 - ServerAdmin i@bogus.in
 - ServerAlias $server_alias
 - DocumentRoot $document_root
 - <Directory $document_root>
 - Options Indexes FollowSymLinks MultiViews
 - AllowOverride All
 - Order allow,deny
 - allow from all
 - </Directory>
 - ErrorLog \${APACHE_LOG_DIR}/$server_alias-error.log;
 - LogLevel warn
 - CustomLog \${APACHE_LOG_DIR}/$server_alias-access.log combined
 - </VirtualHost>
 - HOST;
 
Ну и теперь просто запишем конфиг в файл и напомним пользователю о том, что конфиг теперь нужно еще и активировать с помощью a2ensite:
- file_put_contents(“/etc/apache2/sites-available/$server_alias“, $host_template);
 - echo “Apache config for this hostname created successfully! Don’t forget to run a2ensite $server_alias\n“;
 
Скрипт написан. Нужно сохранить его в файл и не забыть установить флаг +x, чтобы его можно было запускать как программу:
chmod +x a2addsite
Использование
Теперь скрипт можно использовать. Можно как вводить всю информацию в консоли:
% sudo ./a2addsite
Add test.local to your /etc/hosts? (Y/N) [Y]:
Enter your document root [/home/www/test.local]:
Apache config for this hostname created successfully! Don’t forget to run a2ensite test.local
так передавать всю или часть информации скрипту в качестве параметров при вызове:
% sudo ./a2addsite –server-alias=test2.local –add-to-hosts –document-root=default
Apache config for this hostname created successfully! Don’t forget to run a2ensite test2.local
Выводы
PHP можно использовать не только для разработки сайтов, но и для решения мелких локальных задач на компьютере. Скрипт я писал под себя и, наверняка, кто-то из Вас переделает его под свои нужды.
Исходный код скрипта
Литература
Больше информации о потоках ввода вывода, а также о остальных особенностях работы с консолью в PHP можно получить на официальном сайте PHP (англ.):
Command line usage
PHP input/output
Источник: http://habrahabr.ru/post/112146/
https://corp2.info/razrabotka-i-sozdanie-sajtov-internet-magazinov-veb-proektov-kiev-1038.html

Leave a Reply