Инструменты пользователя

Инструменты сайта


www:php-as-cgi

PHP as CGI/FastCGI или configure && make && make install

Введение

Попросили меня разработчики сделать так, чтобы на сервере одновременно работало несколько версий php. Как известно php может работать как модуль apache или в режиме cgi/fastcgi. Но к сожалению, модулем может быть подгружена только одна версия php. В то время как на CGI версии нет никаких ограничений. Вы можете использовать хоть 10 версий одновременно.

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

Итак нам необходимо настроить следующее окружение. php-5.5 будет работать как модуль apache, php-5.4/php-5.3/php-5.2 в режиме FastCGI через модуль mod_fcgid

Итак в нашем распоряжении виртуальная машина с CentOS 6.5 x86_64 (minimal install).

# cat /etc/redhat-release
CentOS release 6.5 (Final)
# uname -a
Linux localhost.localdomain 2.6.32-431.11.2.el6.x86_64 #1 SMP Tue Mar 25 19:59:55 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

Установка php-5.5.12

Это самый простой пункт, просто ставим необходимые пакеты, используя штатный менеджер пакетов yum. Для CentoS рекомендую использовать репозитарий IUS Community

# yum install php55u-cli \
php55u-common \
php55u-dba \
php55u-gd \
php55u-gmp \
php55u-imap \
php55u-intl \
php55u-ldap \
php55u-mbstring \
php55u-mcrypt \
php55u-mysqlnd \
php55u-opcache \
php55u-pdo \
php55u-pear \
php55u-xml

Ну собственно и вся установка. Теперь переходим к самому интересному.

Сборка php-5.4.28

Устанавливаем пакеты, которые нам понадобятся для сборки php.

# yum install gcc-c++ make re2c flex bison libxslt-devel unixODBC-devel readline-devel libicu-devel pam-devel libc-client-devel cyrus-sasl-devel openldap-devel pcre-devel libxml2-devel openssl-devel bzip2-devel curl-devel libjpeg-devel libpng-devel libXpm-devel libtool-ltdl libtool-ltdl-devel libtool freetype-devel t1lib-devel gmp-devel libmcrypt-devel mhash-devel mysql-devel

Наличие тех или иных пакетов будет зависеть от того, какие расширения вы хотите собрать. Например, если вам не нужна поддержка MySQL, то соответственно и нет необходимости в установке пакета mysql-devel.

Скачиваем исходники необходимой нам версии php и распаковываем в любое удобное место. На момент написания статьи в ветке 5.4 - это была версия php-5.4.28.

# wget http://de2.php.net/distributions/php-5.4.28.tar.bz2
# tar -jxvf php-5.4.28.tar.bz2
# cd php-5.4.28

Задаем параметра сборки пакета. По сути указываем какие модули собирать. Так как процедура по сборке довольно таки трудоемкая, то рекомендую собирать все модули, даже те, которые вам не нужны на данный момент. Просто не подгружать их. А если завтра модуль понадобится, то достаточно раскоментировать соответствующую строку с extension и перегрузить apache. В общем тут каждый должен решить сам для себя, что ему будет более удобно.

# ./configure \
--prefix=/opt/php-5.4.28 \
--with-config-file-path=/opt/php-5.4.28/etc \
--with-config-file-scan-dir=/opt/php-5.4.28/etc/php.d \
--with-libdir=lib64 \
--disable-all \
--disable-debug \
--disable-ipv6 \
--disable-cli \
--enable-cgi \
--enable-xml=shared --enable-libxml=shared --enable-dom=shared --enable-simplexml=shared \
--with-xmlrpc=shared --enable-xmlreader=shared --enable-xmlwriter=shared \
--with-xsl=shared --enable-wddx=shared \
--enable-soap=shared \
--enable-pdo=shared \
--with-mysqli=/usr/bin/mysql_config \
--with-mysql=shared,/usr \
--with-pdo-mysql=shared \
--with-mysql-sock=/var/lib/mysql/mysql.sock \
--with-curl=shared \
--enable-exif=shared \
--enable-ftp=shared \
--enable-mbstring=shared --enable-mbregex \
--with-iconv=shared \
--with-gettext=shared \
--enable-bcmath=shared \
--enable-calendar=shared \
--enable-ctype=shared \
--with-gmp=shared \
--with-mhash=shared \
--with-mcrypt=shared \
--enable-sockets=shared \
--enable-session=shared \
--with-bz2=shared --with-zlib=shared --enable-zip=shared \
--with-gd=shared --enable-gd-native-ttf \
--with-t1lib --with-freetype-dir=/usr \
--with-jpeg-dir=/usr \
--with-png-dir=/usr \
--with-xpm-dir=/usr \
--with-openssl=shared \
--with-pcre-regex \
--with-imap=shared --with-imap-ssl \
--with-ldap=shared --with-ldap-sasl \
--enable-intl=shared \
--with-readline=shared \
--with-kerberos=/usr \
--enable-json=shared \
--enable-posix=shared \
--enable-fileinfo=shared \
--enable-phar=shared \
--enable-pcntl

Запускаем саму сборку. В зависимости от мощности компьютера и от количества модулей, сборка может забрать до 30-45 минут. Так что на время сборки можно идти пить кофе.

# make
...
...
...
Build complete.
Don't forget to run 'make test'.

Устанавливаем сам php

# make install
Installing shared extensions:     /opt/php-5.4.28/lib/php/extensions/no-debug-non-zts-20100525/
Installing PHP CGI binary:        /opt/php-5.4.28/bin/
Installing PHP CGI man page:      /opt/php-5.4.28/php/man/man1/
Installing build environment:     /opt/php-5.4.28/lib/php/build/
Installing header files:          /opt/php-5.4.28/include/php/
Installing helper programs:       /opt/php-5.4.28/bin/
  program: phpize
  program: php-config
Installing man pages:             /opt/php-5.4.28/php/man/man1/
  page: phpize.1
  page: php-config.1
Installing PDO headers:          /opt/php-5.4.28/include/php/ext/pdo/

Создаем папку для наших расширений и копируем базовый php.ini

# mkdir -p /opt/php-5.4.28/etc/php.d/
# cp php.ini-production /opt/php-5.4.28/etc/php.ini

Меняем некоторые опции.

# sed -i 's/^;cgi.fix_pathinfo=1$/cgi.fix_pathinfo=1/' /opt/php-5.4.28/etc/php.ini
# sed -i 's/^;date.timezone =/date.timezone=Etc\/UTC/' /opt/php-5.4.28/etc/php.ini

А так мы создаем файл со списком всех расширений, которые мы собрали.

# cd /opt/php-5.4.28/lib/php/extensions/no-debug-non-zts-20100525
# find . -type f -name "*.so" | cut -d '/' -f 2 | sort | awk '{print "extension="$1}' > /opt/php-5.4.28/etc/php.d/extensions.ini

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

# cat /opt/php-5.4.28/etc/php.d/extensions.ini
extension=bcmath.so
extension=bz2.so
extension=calendar.so
extension=ctype.so
extension=curl.so
extension=dom.so
extension=exif.so
extension=ftp.so
extension=gd.so
extension=gettext.so
extension=gmp.so
extension=iconv.so
extension=imap.so
extension=json.so
extension=ldap.so
extension=mbstring.so
extension=mcrypt.so
extension=mhash.so
extension=mysql.so
extension=odbc.so
extension=openssl.so
extension=pdo_mysql.so
extension=pdo_odbc.so
extension=pdo.so
extension=posix.so
extension=readline.so
extension=session.so
extension=soap.so
extension=sockets.so
extension=xmlreader.so
extension=xmlrpc.so
extension=xml.so
extension=xmlwriter.so
extension=xsl.so
extension=zip.so
extension=zlib.so

Сборка php-5.3.28

Проделываем аналогичные операции и для php-5.3

./configure \
--prefix=/opt/php-5.3.28 \
--with-config-file-path=/opt/php-5.3.28/etc \
--with-config-file-scan-dir=/opt/php-5.3.28/etc/php.d \
--with-libdir=lib64 \
--disable-all \
--disable-debug \
--disable-ipv6 \
--disable-cli \
--enable-cgi \
--enable-xml=shared --enable-libxml=shared --enable-dom=shared \
--enable-simplexml=shared \
--with-xmlrpc=shared --enable-xmlreader=shared --enable-xmlwriter=shared \
--with-xsl=shared --enable-wddx=shared \
--enable-soap=shared \
--enable-pdo=shared \
--with-mysqli=/usr/bin/mysql_config \
--with-mysql=shared,/usr \
--with-pdo-mysql=shared \
--with-mysql-sock=/var/lib/mysql/mysql.sock \
--with-curl=shared \
--enable-exif=shared \
--enable-ftp=shared \
--enable-mbstring=shared --enable-mbregex \
--with-iconv=shared \
--with-gettext=shared \
--enable-bcmath=shared \
--enable-calendar=shared \
--enable-ctype=shared \
--with-gmp=shared \
--with-mhash=shared \
--with-mcrypt=shared \
--enable-sockets=shared \
--enable-session=shared \
--with-bz2=shared --with-zlib=shared --enable-zip=shared \
--with-gd=shared --enable-gd-native-ttf \
--with-t1lib --with-freetype-dir=/usr \
--with-jpeg-dir=/usr \
--with-png-dir=/usr \
--with-xpm-dir=/usr \
--with-openssl=shared \
--with-pcre-regex \
--with-imap=shared --with-imap-ssl \
--with-ldap=shared --with-ldap-sasl \
--enable-intl=shared \
--with-readline=shared \
--with-kerberos=/usr \
--enable-json=shared \
--enable-posix=shared \
--enable-fileinfo=shared \
--enable-phar=shared \
--enable-pcntl

Сборка php-5.2.17

Проделываем аналогичные операции и для php-5.2. Стоит обратить внимание, что для 5.2 опции немного отличаются, так мы убрали опции

--enable-fileinfo=shared \
--enable-intl=shared 

и добавили следующие опции

--enable-fastcgi \
--enable-force-cgi-redirect
# ./configure \
--prefix=/opt/php-5.2.17 \
--with-config-file-path=/opt/php-5.2.17/etc \
--with-config-file-scan-dir=/opt/php-5.2.17/etc/php.d \
--with-libdir=lib64 \
--disable-ipv6 \
--disable-all \
--disable-cli \
--disable-debug \
--enable-cgi --enable-fastcgi --enable-force-cgi-redirect \
--enable-xml=shared --enable-libxml=shared --enable-simplexml=shared \
--with-xmlrpc=shared --enable-xmlreader=shared --enable-xmlwriter=shared \
--with-xsl=shared \
--enable-dom=shared \
--enable-soap=shared \
--enable-pdo=shared \
--with-mysqli=/usr/bin/mysql_config --with-mysql=shared,/usr \
--with-pdo-mysql=shared --with-mysql-sock=/var/lib/mysql/mysql.sock \
--with-unixODBC=shared,/usr --with-pdo-odbc=shared,unixODBC,/usr \
--with-curl=shared \
--enable-exif=shared \
--enable-ftp=shared \
--enable-mbstring=shared --enable-mbregex \
--with-gettext=shared \
--with-gmp=shared \
--with-mhash=shared \
--with-mcrypt=shared \
--enable-sockets=shared \
--with-bz2=shared \
--with-zlib=shared \
--enable-zip=shared \
--with-gd=shared --enable-gd-native-ttf \
--with-t1lib \
--with-freetype-dir=/usr \
--with-jpeg-dir=/usr --with-png-dir=/usr --with-xpm-dir=/usr \
--with-openssl=shared \
--with-pcre-regex \
--with-imap=shared --with-imap-ssl \
--with-ldap=shared --with-ldap-sasl \
--with-readline=shared \
--with-kerberos=/usr \
--enable-json=shared \
--enable-posix=shared \
--enable-pcntl \
--enable-calendar=shared \
--enable-ctype=shared \
--enable-bcmath=shared \
--enable-session=shared \
--with-iconv=shared

Сборка php-4.4.9

Данная часть статьи рассчитана скорее на археологов. Но тем не менее, достался мне в наследство один внутренний сервис, который работает на php 4.x, переписывать под 5.x слишком хлопотное задание, по сути там придется переписать весь сервис с нуля. Так что решили оставить. Можно конечно поднять виртуальную машину с CentOS 4.x в которой по умолчанию идет php 4.x, но это не наш путь.

Перед началом сборки необходимо дополнительно установить 3 пакета

# yum install expat-devel sablotron-devel

А 3й пакет zziplib к сожалению отсутствует в стандартных репозитариях, а так же EPEL и RPMForge. Но в принципе это не проблема, так как внутри zziplib-0.13.62.tar.bz2 идет spec файл, все что нам нужно, это собрать и установить необходимый rpm пакет. Если вам не нужна поддержка работы с zip архивами, то данный пункт можно пропустить.

Устанавливаем пакет для сборки rpm

# yum install rpm-build

А затем скачиваем сами исходники и собираем rpm

# cd /root 
# wget http://downloads.sourceforge.net/project/zziplib/zziplib13/0.13.62/zziplib-0.13.62.tar.bz2
# rpmbuild -tb zziplib-0.13.62.tar.bz2
warning: line 39: prereq is deprecated: PreReq: scrollkeeper
error: bad date in %changelog: So Mar 11 2012 guidod <guidod@gmx.de> 0.13.62-1

Но и здесь меня ждала неудача, но мы ведь не сдаемся так просто. По сути в секции Changelog была пропущена одна буква в названии дня.

# tar jxvf zziplib-0.13.62.tar.bz2
# cd zziplib-0.13.62/
# sed -i 's/^\* So/\* Sun/' zziplib.spec
# cd ../
# tar -cf zziplib-0.13.62-1.tar zziplib-0.13.62
# bzip2 zziplib-0.13.62-1.tar
# rpmbuild -tb zziplib-0.13.62-1.tar.bz2
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.uZzQk7
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd /root/rpmbuild/BUILD
+ rm -rf zziplib-0.13.62
+ /usr/bin/bzip2 -dc /root/zziplib-0.13.62.tar.bz2
...
...
...
Wrote: /root/rpmbuild/RPMS/x86_64/zziplib-0.13.62-1.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/zziplib-doc-0.13.62-1.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/zziplib-devel-0.13.62-1.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/zziplib-SDL_rwops-devel-0.13.62-1.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.AgqZLe
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd zziplib-0.13.62
+ /bin/rm -rf /root/rpmbuild/BUILDROOT/zziplib-0.13.62-1.x86_64
+ exit 0

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

# /root/rpmbuild/RPMS/x86_64/
# rpm -ivh zziplib-0.13.62-1.x86_64.rpm zziplib-devel-0.13.62-1.x86_64.rpm
Preparing...                ########################################### [100%]
   1:zziplib                ########################################### [ 50%]
   2:zziplib-devel          ########################################### [100%]

Итак, порядок действий как и с предыдущими версиями php. Задаем опции сборки, указав какие модули собирать

# ./configure \
--prefix=/opt/php-4.4.9 \
--with-config-file-path=/opt/php-4.4.9/etc --with-config-file-scan-dir=/opt/php-4.4.9/etc/php.d \
--disable-ipv6 \
--disable-all \
--disable-cli \
--disable-debug \
--enable-cgi --enable-fastcgi \
--enable-discard-path --enable-force-cgi-redirect \
--enable-memory-limit \
--enable-wddx=shared \
--enable-xml=shared --with-xmlrpc=shared \
--with-dom=shared --with-dom-xslt --with-dom-exslt \
--enable-xslt=shared --with-xslt-sablot \
--with-expat-dir=/usr \
--with-mysql=shared,/usr --with-mysql-sock=/var/lib/mysql/mysql.sock \
--with-unixODBC=shared,/usr \
--with-curl=shared \
--enable-exif=shared \
--enable-ftp=shared \
--with-ncurses=shared \
--enable-mbstring=shared \
--enable-mbregex \
--with-gettext=shared \
--with-gmp=shared \
--with-mhash=shared \
--with-mcrypt=shared \
--enable-sockets=shared \
--with-bz2=shared \
--with-zlib=shared \
--with-zip=shared \
--with-gd=shared \
--enable-gd-native-ttf \
--with-t1lib \
--with-freetype-dir=/usr \
--with-jpeg-dir=/usr \
--with-png-dir=/usr \
--with-xpm-dir=/usr \
--with-openssl=shared \
--with-pcre-regex \
--with-imap=shared \
--with-imap-ssl \
--with-ldap=shared \
--with-readline=shared \
--with-kerberos=/usr \
--enable-posix=shared \
--enable-pcntl \
--enable-calendar=shared \
--enable-ctype=shared \
--enable-bcmath=shared \
--with-iconv=shared

Но собрать php-4.4.9 мне не удалось, компиляция останавливалась со следующими ошибками

/bin/sh /root/php-4.4.9/libtool --silent --preserve-dup-deps --mode=compile gcc  -Iext/openssl/ -I/root/php-4.4.9/ext/openssl/ -DPHP_ATOM_INC -I/root/php-4.4.9/include -I/root/php-4.4.9/main -I/root/php-4.4.9 -I/usr/include/libxml2 -I/usr/include/freetype2 -I/usr/include/imap -I/root/php-4.4.9/ext/mbstring/mbregex -I/root/php-4.4.9/ext/mbstring/libmbfl -I/root/php-4.4.9/ext/mbstring/libmbfl/mbfl -I/usr/include/mysql -I/usr/include/ncurses -I/root/php-4.4.9/TSRM -I/root/php-4.4.9/Zend    -g -O2   -c /root/php-4.4.9/ext/openssl/openssl.c -o ext/openssl/openssl.lo
/root/php-4.4.9/ext/openssl/openssl.c:182: error: expected specifier-qualifier-list before 'LHASH'
/root/php-4.4.9/ext/openssl/openssl.c:343: error: expected declaration specifiers or '...' before 'LHASH'
/root/php-4.4.9/ext/openssl/openssl.c: In function 'php_openssl_config_check_syntax':
/root/php-4.4.9/ext/openssl/openssl.c:348: error: 'config' undeclared (first use in this function)
/root/php-4.4.9/ext/openssl/openssl.c:348: error: (Each undeclared identifier is reported only once
/root/php-4.4.9/ext/openssl/openssl.c:348: error: for each function it appears in.)
/root/php-4.4.9/ext/openssl/openssl.c: In function 'add_oid_section':
/root/php-4.4.9/ext/openssl/openssl.c:366: error: 'struct php_x509_request' has no member named 'req_config'
/root/php-4.4.9/ext/openssl/openssl.c:370: error: 'struct php_x509_request' has no member named 'req_config'
/root/php-4.4.9/ext/openssl/openssl.c: In function 'php_openssl_parse_config':
/root/php-4.4.9/ext/openssl/openssl.c:416: error: 'struct php_x509_request' has no member named 'config_filename'
/root/php-4.4.9/ext/openssl/openssl.c:416: error: 'struct php_x509_request' has no member named 'config_filename'
/root/php-4.4.9/ext/openssl/openssl.c:417: error: 'struct php_x509_request' has no member named 'section_name'
/root/php-4.4.9/ext/openssl/openssl.c:417: error: 'struct php_x509_request' has no member named 'section_name'
/root/php-4.4.9/ext/openssl/openssl.c:418: error: 'struct php_x509_request' has no member named 'global_config'
/root/php-4.4.9/ext/openssl/openssl.c:419: error: 'struct php_x509_request' has no member named 'req_config'
/root/php-4.4.9/ext/openssl/openssl.c:419: error: 'struct php_x509_request' has no member named 'config_filename'
/root/php-4.4.9/ext/openssl/openssl.c:421: error: 'struct php_x509_request' has no member named 'req_config'
/root/php-4.4.9/ext/openssl/openssl.c:426: error: 'struct php_x509_request' has no member named 'req_config'
/root/php-4.4.9/ext/openssl/openssl.c:437: error: 'struct php_x509_request' has no member named 'digest_name'
/root/php-4.4.9/ext/openssl/openssl.c:437: error: 'struct php_x509_request' has no member named 'digest_name'

Как видно, проблема с модулем openssl. Потратив немного времени на поиск, я смог найти измененный файл openssl.c, который нам необходимо скопировать поверх оригинального. Кому интересно, может посмотреть diff между двумя версиями файлов.

# cd /root
# wget http://www.logicwreck.com/wp-content/files/openssl.c
# cp openssl.c php-4.4.9/ext/openssl/
cp: overwrite `php-4.4.9/ext/openssl/openssl.c'? y

После этого сборка прошла успешно.

Настройка apache и mod_fcgid

Самая сложная работа уже позади, теперь только осталось все это соединить воедино и настроить. Чем мы собственно и займемся. Устанавливаем сам модуль и правим конфигурационный файл

# yum install mod_fcgid
# cat /etc/httpd/conf.d/fcgid.conf
LoadModule fcgid_module modules/mod_fcgid.so
FcgidIPCDir /var/run/mod_fcgid
FcgidProcessTableFile /var/run/mod_fcgid/fcgid_shm
FcgidFixPathinfo 1

Теперь, все что нам осталось, это указать apache, что необходимо использовать cgi версию php. Собственно сделать это можно несколькими способами. Например, в описании виртуального хоста необходимо добавить следующие строки

<FilesMatch \.php$>
   FcgidWrapper /opt/php-5.2.17/bin/php-cgi .php
   AddHandler fcgid-script .php
</FilesMatch>

Если же вы хотите, чтобы в пределах одного виртуального хоста была одновременная поддержка нескольких версий, в зависимости от расширения файла, то настройки будут следующими

<FilesMatch \.php52$>
   FcgidWrapper /opt/php-5.2.17/bin/php-cgi .php52
   AddHandler fcgid-script .php52
</FilesMatch>

<FilesMatch \.php53$>
   FcgidWrapper /opt/php-5.3.28/bin/php-cgi .php53
   AddHandler fcgid-script .php53
</FilesMatch>

В общем все зависит от потребностей разработчиков. С такими настройками все файлы с расширением .php будут обрабатываться модулем apache php-5.5.12, файлы с расширением .php53 будут обрабатываться cgi версией php 5.3.28 и соответственно файлы с расширением .php52 будут обрабатываться cgi версией php 5.2.17

Так же необходимое условие работы данной системы, чтобы правильно работал cgi вы должны выставить опцию +ExecCGI на корень виртуального хоста или как вариант папку, в которой будут находиться соотв файлы.

Привожу полный конфигурационный файл виртуального хоста

# cat php-cgi.example.net.conf
<VirtualHost *:80>
    ServerAdmin webmaster@example.net
    ServerName php-cgi.example.net

    DocumentRoot /vhosts/php-cgi

    <FilesMatch \.php52$>
        FcgidWrapper /opt/php-5.2.17/bin/php-cgi .php52
        AddHandler fcgid-script .php52
    </FilesMatch>

    <FilesMatch \.php53$>
        FcgidWrapper /opt/php-5.3.28/bin/php-cgi .php53
        AddHandler fcgid-script .php53
    </FilesMatch>
    
    <FilesMatch \.php54$>
        FcgidWrapper /opt/php-5.4.28/bin/php-cgi .php54
        AddHandler fcgid-script .php54
    </FilesMatch>

    <Directory /vhosts/php-cgi>
        Options -Indexes +ExecCGI
        AllowOverride all
        Order allow,deny
        allow from all
    </Directory>
</VirtualHost>

Либо вы можете разрешить самим разработчикам переключать версии php через .htaccess файл. Т.е. из описания виртуального хосты мы убираем все FilesMatch. Таким образом, по дефолту сайт будет работать на php-5.5.12, а в случае необходимости переключиться на php-5.2.17 необходимо будет добавить следующие строки в .htaccess

# cat .htaccess
<FilesMatch \.php>
    FcgidWrapper /opt/php-5.2.17/bin/php-cgi .php
    AddHandler fcgid-script .php
</FilesMatch>

В общем тут все ограничивается вашей фантазией и требованиями проекта/разработчиков.

Полезные статьи

www/php-as-cgi.txt · Последние изменения: 2015/08/17 17:19 — root