Versões de PHP diferente em cada virtual host na mesma máquina.

Um belo dia precisei dar suporte em dois projetos rodando PHP, legal mas um projeto roda usando PHP 5.2 e tinha que ter os módulos de memcache, APC e um módulo de radicalização de palavras chamado php-stemmer . O outro tinha que rodar em PHP 5.3 com os módulos mod_rewrite e mcrypt. Ok mas eu tenho uma máquina só, como faz?

Estratégia: usar o ambiente com as instalações padrões ou seja, com PHP 5.3 e módulos instalados normalmente com apt-get install, ou aptitude install, ou yum install. E uma instalação de PHP 5.2 compilada na unha com os módulos e tudo mais rodando em CGI ou Fast CGI.

Após tentativas incessantes de compilar o PHP 5.2.7 no Ubuntu 11.10 de diversas maneiras diferentes além de perder alguns acabei ficando muito irritado ao ponto de desistir por algum tempo.

Meu brother Erick Müller mais conhecido lá no escritório como o Nave conseguiu compilar e rodar versões diferentes de PHP usando CGI mas em uma instalação de 32bits. Como precisava trabalhar montei uma Virtual Machine com ubuntu server, fiz downgrade da instalação do PHP para 5.2 e montei localmente com SSHFS (SSH FileSystem).

Graças à insistência do Erick tentamos refazer isso no Fedora 16 e impressionantemente foi uma manteiga.

Partindo nessa aventura voltei a usar Fedora depois de muitos anos (a última vez que usei algo padrão Red Hat foi o próprio Red Hat 7.3 … Na verdade cheguei a usar o Fedora Core 6 uma ou duas vezes na faculdade)

Talk is cheap, show me the code, então vamo que vamos:

Assumindo papel de root:

    su -

Supondo que pegamos um Fedora 16 zerado novinho, instalamos pacotes necessários para compilação:

    yum install automake gcc

Instalamos o Apache2, o PHP 5.3 e os módulos do PHP necessários para uso nos projetos PHP 5.3 através dos repositórios:

    yum install php php-pecl-apc php-common php-cli php-pear php-pdo php-mysql memcached php-pecl-memcache php-pecl-memcached php-gd php-mbstring php-mcrypt php-xml php-pecl-xdebug

Instalamos o MySQL Server:

    yum install mysql mysql-server

Na sequência já subimos o serviço, colocamos na inicialização do sistema e fizemos a primeira configuração para usar o MySQL:

    systemctl start mysqld.service
    systemctl enable mysqld.service
    /usr/bin/mysql_secure_installation

    Definir a senha do usuário root:
    Remove anonymous users? [Y/n] Y
    Disallow root login remotely? [Y/n] Y
    Remove test database and access to it? [Y/n] Y
    Reload privilege tables now? [Y/n] Y

Voltando ao PHP instalamos os pacotes necessários para compilação:

    yum install libtool httpd-devel aspell-devel apr-devel gcc libxml2-devel bzip2-devel zlib-devel curl-devel libmcrypt-devel libjpeg-devel libpng-devel gd-devel libtool http-devel apr-devel mysql-devel libmhash mhash-devel libpspell pspell-devel aspell-devel openssl-devel libpng-devel freetype-devel libmcrypt-devel pam-devel freetype-devel libtidy-devel expat-devel libxslt-devel libc-client-devel mm-devel libX11-devel mod_fcgid libtool-ltdl-devel

Adicionamos o usuário da máquina ao grupo apache. Supondo que o usuario da máquina seja zezinho fica:

    usermod –append –groups apache zezinho

Em seguida baixamos os pacotes na pasta home (neste caso a home do usuário root):

    cd ~
    wget -c http://us3.php.net/get/php-5.2.17.tar.gz/from/br.php.net/mirror
    wget -c http://us3.php.net/get/php-5.4.0.tar.gz/from/br.php.net/mirror

Descompactamos o php52 e o php 54:

    cd ~
    tar -zxvf php-5.2.17.tar.gz
    tar -zxvf php-5.4.0.tar.gz

Primeiro entramos na pasta do PHP 5.2.17:

    cd php-5.2.17

Preparamos o configurator com o pequeno comandinho (sugestão, coloque dentro de um arquivo sh, dê permissão de execussão e execute-o):

    ./configure --prefix=/opt/php5.2.17 --enable-fastcgi --with-curl \
    --with-curlwrappers --with-freetype-dir=/usr \
    --with-imap=/opt/php_with_imap_client/ --with-imap-ssl=/usr \
    --with-gettext --with-ttf --enable-mbstring --with-openssl \
    --enable-shmop --enable-sockets --with-pear --with-pdo-mysql=shared \
    --with-pdo-sqlite=shared --with-sqlite=shared --with-tidy --with-ttf \
    --with-pic --enable-pdo=shared --enable-safe-mode --with-png-dir \
    --with-pcre-regex --with-mcrypt --with-mhash --with-libdir=lib64 \
    --with-libexpat-dir=/usr --with-config-file-path=/opt/php5.2.17 \
    --with-config-file-scan-dir=/opt/php5.2.17/php.d --enable-bcmath \
    --enable-calendar --enable-dbase --enable-exif --enable-ftp \
    --enable-mbstring --enable-pcntl --enable-soap --enable-sockets \
    --enable-sqlite-utf8 --enable-wddx --enable-zend-multibyte \
    --enable-zip --with-bz2 --with-zlib --with-gettext --enable-cli \
    --with-pear --with-openssl=/usr --with-iconv --with-mysql --with-mysqli \
    --enable-mbstring --enable-exif --with-jpeg-dir=/usr --with-kerberos \
    --with-zlib --with-zlib-dir --with-png-dir=/usr --with-gd --with-gettext \
    --enable-gd-native-ttf --enable-libxml --with-xmlrpc --with-xpm-dir \
    --with-xsl --with-mhash --with-pspell --with-mcrypt --enable-bcmath \
    --with-mime-magic --with-mm --enable-magic-quotes --enable-sockets \
    --enable-soap --enable-calendar --enable-force-cgi-redirect

Compilamos:

    make

E instalamos em /opt/php5.2.17:

    make install

Copiamos o arquivo ini:

    cp ./php.ini-recommended /opt/php5.2.17/php.ini

Editamos o php.ini (Atenção, as confs abaixo são para ambiente de desenvolvimento, onde precisamos melhorar apresentação de mensagens de erros, warnings e notices, e com isso fazer as devidas correções):

    vim /opt/php5.2.17/php.ini

Descomentar e alterar short_open_tag para Off:

    short_open_tag = Off

Descomentar e alterar error_reporting para E_ALL:

    error_reporting = E_ALL

Descomentar e alterar display_errors para ON:

    display_errors = On

Descomentar e alterar html_errors para On:

    html_errors = On

Comentar a linha extension_dir:

    ;extension_dir = "./"

Por fim criamos a pasta onde vão ficar os arquivos ini adicionais como definimos no ./configure:

    mkdir /opt/php5.2.17/php.d

De maneira análoga vamos preparar o PHP 5.4.0:

    cd ~/php-5.4.0

    ./configure --prefix=/opt/php5.4.0 --enable-fastcgi --with-curl \
    --with-curlwrappers --with-freetype-dir=/usr \
    --with-imap=/opt/php_with_imap_client/ --with-imap-ssl=/usr \
    --with-gettext --with-ttf --enable-mbstring --with-openssl \
    --enable-shmop --enable-sockets --with-pear --with-pdo-mysql=shared \
    --with-pdo-sqlite=shared --with-sqlite=shared --with-tidy --with-ttf \
    --with-pic --enable-pdo=shared --enable-safe-mode --with-png-dir \
    --with-pcre-regex --with-mcrypt --with-mhash --with-libdir=lib64 \
    --with-libexpat-dir=/usr --with-config-file-path=/opt/php5.4.0 \
    --with-config-file-scan-dir=/opt/php5.4.0/php.d --enable-bcmath \
    --enable-calendar --enable-dbase --enable-exif --enable-ftp \
    --enable-mbstring --enable-pcntl --enable-soap --enable-sockets \
    --enable-sqlite-utf8 --enable-wddx --enable-zend-multibyte --enable-zip \
    --with-bz2 --with-zlib --with-gettext --enable-cli --with-pear \
    --with-openssl=/usr --with-iconv --with-mysql --with-mysqli \
    --enable-mbstring --enable-exif --with-jpeg-dir=/usr --with-kerberos \
    --with-zlib --with-zlib-dir --with-png-dir=/usr --with-gd --with-gettext \
    --enable-gd-native-ttf --enable-libxml --with-xmlrpc --with-xpm-dir \
    --with-xsl --with-mhash --with-pspell --with-mcrypt --enable-bcmath \
    --with-mime-magic --with-mm --enable-magic-quotes --enable-sockets \
    --enable-soap --enable-calendar --enable-force-cgi-redirect

Compilamos:

    make

E instalamos em /opt/php5.4.0:

    make install

Também copiamos o php.ini:

    cp ./php.ini-development /opt/php5.4.0/php.ini

Também editamos preparando como uma máquina de desenvolvimento:

    vim /opt/php5.4.0/php.ini

Descomentar e alterar short_open_tag para Off:

    short_open_tag = Off

Descomentar e alterar error_reporting para E_ALL:

    error_reporting = E_ALL

Descomentar e alterar display_errors para ON:

    display_errors = On

Descomentar e alterar html_errors para On:

    html_errors = On

Comentar a linha extension_dir:

    ;extension_dir = “./”

Por fim também criamos a pasta onde vão ficar os arquivos ini adicionais como definimos no ./configure

    mkdir /opt/php5.4.0/php.d

Fontes já compilados e instalados agora falta configurar o fastcgi:

    vim /var/www/cgi-bin/php5.2.17.fcgi

Inserimos o conteúdo:

    #!/bin/bash
    PHP_CGI=/opt/php5.2.17/bin/php-cgi
    PHP_FCGI_CHILDREN=4
    PHP_FCGI_MAX_REQUESTS=1000
    export PHP_FCGI_CHILDREN
    export PHP_FCGI_MAX_REQUESTS
    exec $PHP_CGI

Também fazemos com o PHP 5.4:

    vim /var/www/cgi-bin/php5.4.0.fcgi

Com o conteúdo:

    #!/bin/bash
    PHP_CGI=/opt/php5.4.0/bin/php-cgi
    PHP_FCGI_CHILDREN=4
    PHP_FCGI_MAX_REQUESTS=1000
    export PHP_FCGI_CHILDREN
    export PHP_FCGI_MAX_REQUESTS
    exec $PHP_CGI

Corrigimos o dono e o permissionamento dos arquivos fastcgi:

    chmod 744 /var/www/cgi-bin/php5.2.17.fcgi
    chmod 744 /var/www/cgi-bin/php5.4.0.fcgi
    chown apache:apache /var/www/cgi-bin/php5.2.17.fcgi
    chown apache:apache /var/www/cgi-bin/php5.4.0.fcgi

Criamos as pastas onde ficarão os arquivos de cada virtualhost:

    mkdir /var/www/html/php52
    mkdir /var/www/html/php53
    mkdir /var/www/html/php54

Alteramos o dono dessas pastas para seu usuário. Vamos supor que seu usuário seja zezinho:

    chown zezinho:apache /var/www/html/php52
    chown zezinho:apache /var/www/html/php53
    chown zezinho:apache /var/www/html/php54

Preparamos o Apache para trabalhar com VirtualHosts:

    vim /etc/httpd/conf/httpd.conf

E descomentamos a linha:

    NameVirtualHost *:80

Criamos os VirtualHosts:

    vim /etc/httpd/conf.d/vhost-php52.inet.conf
    vim /etc/httpd/conf.d/vhost-php53.inet.conf
    vim /etc/httpd/conf.d/vhost-php54.inet.conf

O conteúdo do vhost-php52.inet.conf vai ficar assim:

    <VirtualHost *:80>
            ServerName php52.inet
            DocumentRoot /var/www/html/php52
            <Directory /var/www/html/php52>
                    Options -Indexes FollowSymLinks +ExecCGI
                    AllowOverride AuthConfig FileInfo
                    AddHandler php5-fastcgi .php
                    Action php5-fastcgi /cgi-bin/php5.2.17.fcgi
                    DirectoryIndex index.php index.html
                    AllowOverride All
                    Order allow,deny
                    Allow from all
            </Directory>
            CustomLog /etc/httpd/logs/php52.inet.log combined
            ErrorLog /etc/httpd/logs/php52.inet.error.log
    </VirtualHost>

O conteúdo do vhost-php54.inet.conf vai ficar assim:

    <VirtualHost *:80>
            ServerName php54.inet
            DocumentRoot /var/www/html/php54
            <Directory /var/www/html/php54>
                    Options -Indexes FollowSymLinks +ExecCGI
                    AllowOverride AuthConfig FileInfo
                    AddHandler php5-fastcgi .php
                    Action php5-fastcgi /cgi-bin/php5.4.0.fcgi
                    DirectoryIndex index.php index.html
                    AllowOverride All
                    Order allow,deny
                    Allow from all
            </Directory>
            CustomLog /etc/httpd/logs/php54.inet.log combined
            ErrorLog /etc/httpd/logs/php54.inet.error.log
    </VirtualHost>

O conteúdo do vhost-php53.inet.conf vai ficar um pouco diferente:

    <VirtualHost *:80>
            ServerName php53.inet
            DocumentRoot /var/www/html/php54
            <Directory /var/www/html/php54>
                    Options -Indexes FollowSymLinks
                    DirectoryIndex index.php index.html
                    AllowOverride All
                    Order allow,deny
                    Allow from all
            </Directory>
            CustomLog /etc/httpd/logs/php53.inet.log combined
            ErrorLog /etc/httpd/logs/php53.inet.error.log
    </VirtualHost>

Para testar precisamos ter esse VirtualHosts colocados na nossa lista de hosts:

    vim /etc/hosts

E inserimos as linhas abaixo no final:

    127.0.0.1    php52.inet
    127.0.0.1    php53.inet
    127.0.0.1    php54.inet

Para mostrar a instalação funcionando usamos um arquivo com o comando phpinfo();

Para criar os arquivos deslogamos o usuário root:

    logout

Assim voltamos a ser o usuário da máquina, aqui no nosso exemplo zezinho. Como zezinho vamos criar o arquivo info.php:

    vim /var/www/html/php52/info.php

E colocamos o conteúdo:

     <?php phpinfo(); ?>

Copiamos o arquivo para as pastas dos outros VirtualHosts:

    cp /var/www/html/php52/info.php /var/www/html/php53/info.php
    cp /var/www/html/php52/info.php /var/www/html/php54/info.php

Reiniciamos o apache:

    service httpd restart

Taaadaaammmm:

Para colocar os módulos devemos compilá-los um a um usando o phpize da versão que instalamos e o ./configure com o parâmetro –with-php-config= apontando para o path onde está o binário php-config. E aí? Mãos na massa?

Bom para o xdebug fizemos assim. Assumimos o papel de root novamente:

    su -

Baixamos o fonte do Xdebug:

    cd ~
    pear download pecl/xdebug

Descompactamos:

    tar -xzvf xdebug-x.x.x.tgz  # (quando testamos era a xdebug-2.2.0RC1.tgz)

Entramos no diretório e preparamos usando o phpize da versão que vamos instalar:

    cd xdebug-x.x.x
    /opt/php5.2.17/bin/phpize

Configuramos com a opção do diretório com o nosso php-config:

    ./configure –with-php-config=/opt/php5.2.17/bin/php-config

Compilamos:

    make

E Instalamos:

    make install

Criamos / Editamos o arquivo de configuração:

    vim /opt/php5.2.17/php.d/xdebug.ini

Com o conteúdo:

    ; Enable xdebug extension module
    zend_extension=/opt/php5.2.17/lib/php/extensions/no-debug-non-zts-20060613/xdebug.so
    xdebug.remote_enable=1
    xdebug.remote_handler=dbgp
    xdebug.remote_mode=req
    xdebug.remote_host=127.0.0.1
    xdebug.remote_port=9000

Para o módulo de Memcache fizemos similar. Baixamos o fonte:

    cd ~
    pear download pecl/memcache

Descompactamos:

    tar -vzxf memcache-2.2.6.tgz

Entramos no diretório descompactadoe preparamos a instalação:

    cd memcache-2.2.6
    /opt/php5.2.17/bin/phpize

Configuramos com o diretório do php-config:

    ./configure –with-php-config=/opt/php5.2.17/bin/php-config

Compilamos:

    make

E instalamos:

    make install

Criamos/Editamos o arquivo ini:

    vim /opt/php5.2.17/php.d/memcache.ini

E colocamos o conteúdo:

    extension=memcache.so

Para o módulo de APC também bem similar. Download:

    cd ~
    pear download pecl/apc

Descompactar:

    tar -zxvf APC-3.1.9.tgz

Entrar e preparar:

    cd APC-3.1.9/
    /opt/php5.2.17/bin/phpize

Configurar com o path do php-config:

    ./configure –with-php-config=/opt/php5.2.17/bin/php-config

Compilar:

    make

Instalar:

    make install

E criar o arquivo ini:

    vim /opt/php5.2.17/php.d/apc.ini

Nesse colocamos o conteúdo:

    extension=apc.so
    apc.enabled=1
    apc.shm_size=128M
    apc.ttl=7200
    apc.user_ttl=7200
    apc.enable_cli=1

É isso ai cambada, comigo está funcionando bem aqui. Erick, dá uma zoiada. Se esqueci de algo me avisa que editamos.

Sugestões e xingamentos abaixo

té +