Локальный веб-сервер под Linux, с автоматическим поднятием хостов и переключением версий PHP

в 12:56, , рубрики: Apache, apache2, dnsmasq, fastcgi, php, postfix, vhost_alias

Скорее всего какие-то части этой статьи уже знакомы многим хаброжителям, но в связи с покупкой нового рабочего ноутбука я решил собрать все крупинки воедино и организовать удобное средство для разработки. Мне часто приходится работать со множеством маленьких проектов, с разными версиями PHP, часто переводить старые проекты на новые версии. В далёком прошлом, когда я был пользователем Windows то использовал OpenServer. Но с переходом на Linux мне нехватало той простоты создания хостов и переключений версий которые были в нём. Поэтому пришлось сделать еще более удобное решение на Linux =)

Цели

  1. Использовать текущий на момент написания статьи софт
  2. Чтоб разграничить локальные домены, будем использовать специальный домен .loc
  3. Переключения версий PHP реализуем через поддомен c помощью fast-cgi
  4. Автоматическое создание хоста с помощью vhost_alias и dnsmasq

Что имеем в итоге. При переходе на

56.test.loc

Apache запустит c версией PHP 5.6.36

/var/www/test.loc/public_html/index.php

Поменяв поддомен на

72.test.loc

будет запущен тот же файл но уже с версией PHP 7.2.7

Другие версии доставляются аналогичным описанным ниже способом.

Для создания еще одного сайта просто создаем в /var/www/ папку имеющую окончание .loc, внутри которой должна быть папка public_html являющаяся корнем сайта

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

Всё это я проверну на LinuxMint19, он на базе Ubuntu18.04, так что с ним все будет аналогично.

Для начала поставим необходимые пакеты

sudo apt update
sudo apt install build-essential pkg-config libxml2-dev libfcgi-dev apache2 libapache2-mod-fcgid postfix

Postfix ставим в качестве плюшки, как простое решение(в мастере установки, всё по умолчанию выбираем) для отправки почты с локальной машины.

Так как это локальная разработка и я единственный пользователь. То мне удобней перенести папку с проектами в мою домашнюю дерикторию. Она у меня маунтится отдельным диском и мигрирует при переустановке системы. Самый простой способ это создать ссылку, тогда не нужно менять пути в настройках да и путь привычный для всех.

Скопируем папку созданную апачем в домашний каталог, создадим на ее месте ссылку, не забыв поменять пользователя на себя и обменяться группами с апачем.

sudo mv /var/www/ ~/www
sudo ln -s ~/www /var/www
sudo chown $USER:$USER -R ~/www
sudo usermod -a -G www-data $USER
sudo usermod -a -G $USER www-data

Создадим папку в которой будем собирать исходники PHP для разных версий

sudo mkdir /usr/local/src/php-build

Также нам понадобится папки для CGI скриптов

sudo mkdir /var/www/cgi-bin

И runtime папка для этих же скриптов, с правами

sudo mkdir /var/run/mod_fcgid
sudo chmod 777 /var/run/mod_fcgid

У меня dnsmasq-base идет с коробки, если нет то его всегда можно доставить.

Добавим правило в его конфигурацию. Найти файл конфигурации dnsmasq.conf можно так

sudo updatedb
locate dnsmasq.conf

Добавим в него строчку для перенаправление нашего локального домена на локальную машину.

address=/loc/127.0.0.1

Также нужно включить необходимые модули апача

sudo a2enmod fcgid vhost_alias actions 

Предварительная подготовка завершена, приступаем к сборке различных локальных версий PHP. Для каждой версии PHP проделываем следующие 4 шага. На примере 5.6.36

1. Скачиваем исходники нужной версии и распаковываем их

cd /usr/local/src/php-build
sudo wget http://pl1.php.net/get/php-5.6.36.tar.bz2/from/this/mirror -O php-5.6.36.tar.bz2
sudo tar jxf php-5.6.36.tar.bz2

2. Cобираем из исходников нужную версию PHP, и помещаем ее в /opt/php-5.6.36

sudo mkdir /opt/php-5.6.36
cd php-5.6.36
sudo ./configure --prefix=/opt/php-5.6.36 --with-config-file-path=/opt/php-5.6.36 --enable-cgi
sudo make
sudo make install
sudo make clean

3. Создаем CGI для обработки этой версии в /var/www/cgi-bin/php-5.6.36.fcgi

#!/bin/bash
PHPRC=/opt/php-5.6.36/php.ini
PHP_CGI=/opt/php-5.6.36/bin/php-cgi
PHP_FCGI_CHILDREN=8
PHP_FCGI_MAX_REQUESTS=3000
export PHPRC
export PHP_FCGI_CHILDREN
export PHP_FCGI_MAX_REQUESTS
exec /opt/php-5.6.36/bin/php-cgi

4. Делаем файл исполняемым

sudo chmod +x /var/www/cgi-bin/php-5.6.36.fcgi

5. Добавляем экшен для обработки каждой версии в /etc/apache2/mods-available/fcgid.conf

<IfModule mod_fcgid.c>
  AddHandler fcgid-script fcg fcgi fpl

  Action application/x-httpd-php-5.6.36 /cgi-bin/php-5.6.36.fcgi
  AddType application/x-httpd-php-5.6.36 .php

  #Action application/x-httpd-php-7.2.7 /cgi-bin/php-7.2.7.fcgi
  #AddType application/x-httpd-php-7.2.7 .php

  FcgidIPCDir /var/run/mod_fcgid
  FcgidProcessTableFile /var/run/mod_fcgid/fcgid_shm

  FcgidConnectTimeout 20

  <IfModule mod_mime.c>
    AddHandler fcgid-script .fcgi
  </IfModule>
</IfModule>

6. Добавляем правило для обработки каждой версии в /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
        #Универсальный ServerNamе
        ServerAlias *.loc
        #Алиас для CGI скриптов
        ScriptAlias /cgi-bin /var/www/cgi-bin
        #Универсальный DocumentRoot
        VirtualDocumentRoot /var/www/%2+/public_html

        #Директория тоже должна быть универсальной
        <Directory /var/www/*.loc/>
            Options +ExecCGI -Indexes
            AllowOverride All
            Order allow,deny
            Allow from all
            <FilesMatch .php$>
                #Ниже все условия для каждой из версий
                <If "%{SERVER_NAME} =~ /56..*?.loc/">
                    SetHandler application/x-httpd-php-5.6.36
                </If>
                #<ElseIf "%{SERVER_NAME} =~ /72..*?.loc/">
                #    SetHandler application/x-httpd-php-7.2.7
                #</ElseIf>
                <Else>
                    #По умолчанию, если версия не указанна, запускаем на последней
                    SetHandler application/x-httpd-php56
                </Else>
            </FilesMatch>
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Ну вот и всё. Осталось только перезапустить apache и dnsmasq и пользоваться

sudo service apache2 restart
sudo service network-manager restart

Поместим в index.php нового тестового сайта phpinfo() и проверим что все работает.

Автор: Ромчик

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js