How To Run Multiple PHP Versions

The PHP programming language has gone long way since its beginnings. It made another big step by making it easy and convenient to run Apps in different versions of PHP at the same time. In this post, I go over the compiling of any PHP Version you wish, installation of the PHPFarm technology and the configuration of the Apache web server, all of which part of the task to run different PHP versions simultaneously on one machine with different apps

System: Ubuntu 14, Apache 2.4, LAMP

Installation of PHPFarm

Before compiling different versions of PHP, we install the PHPFarm. To do so

Step 1 – Install supporting necessary libraries:
udo apt-get install libxml2 libxml2-dev libssl-dev
sudo apt-get install libcurl4-openssl-dev pkg-config
sudo apt-get install libcurl4-gnutls-dev libjpeg-dev libpng12-dev libmysqlclient-dev
Step 2 – Install the PHPFarm

We grab the PHPFarm from PHPFarm Git repo

cd /home/tools
sudo git clone https://github.com/cweiske/phpfarm

This will clone PHPFarm at /home/tools/phpfarm directory

Compile PHP Versions

Once, we have the PHPFarm, lets compile some version of PHP.

Step 3 – Custom Configurations

First, we specify some custom configurations for new php version. Go to the ‘src’ directory of PHPFarm and create file of certain naming

cd /home/tools/phpfarm/src
sudo vim custom-options-5.3.29.sh

For some example of custom options, please see AmacGregor Git Repo
In our case, we use the following custom options by inserting them in the /home/tools/phpfarm/srccustom-options-5.3.29.sh:

#gcov='--enable-gcov'
configoptions="\
--enable-bcmath \
--enable-calendar \
--enable-exif \
--enable-ftp \
--enable-mbstring \
--enable-pcntl \
--enable-soap \
--enable-sockets \
--enable-sqlite-utf8 \
--enable-wddx \
--enable-zip \
--disable-debug \
--with-mysql \
--with-zlib \
--with-gettext \
--with-pdo-mysql \
--with-curl \
--with-openssl \
$gcov"
Step 4 – Compile PHP

Next, we compile new PHP version with our custom options:

cd /home/tools/phpfarm/src
sudo ./compile.sh 5.3.29

This will generate new version of PHP 5.3.29. Afterwards, test that it is working

cd /home/tools/phpfarm/inst/bin
./php-5.3.29 --version

Configure Virtual Host of Apache For Certain Version

Step 5 – Install supporting modules of PHPFarm for Apache

The FastCGI is technology to incorporate PHPFarm into Apache, so we are installing supporting libraries

sudo apt-get install libapache2-mod-fastcgi apache2-mpm-worker apache2-suexec
sudo a2enmod actions fastcgi suexec
sudo service apache2 restart

After restarting Apache service, the newly installed modules are included

Step 6 – Mapping CGI to PHPFarm

Next, we create web directory with configurations to map each PHP Version to the CGI service of Apache

sudo mkdir /var/www/cgi-bin
cd /var/www/cgi-bin
sudo vip php-cgi-5.3.29

Afterwards, we are adding mapping in form of Bash script named php-cgi-5.3.29 as follows

#!/bin/sh
PHPRC="/etc/php5/cgi/5.3.29/"
export PHPRC
PHP_FCGI_CHILDREN=3
export PHP_FCGI_CHILDREN
PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS
exec /home/tools/phpfarm/inst/bin/php-cgi-5.3.29

As you see the last line it maps to our PHP version. The variable “PHPRC” also specifies the location of php.ini file to use. By default, it uses the php.ini in the dir of /home/tools/phpfarm/inst/php-cgi-5.3.29/lib.php

Make our file of mapping is executable and chown rights to apache user („www-data“ by default):

sudo chmod +x /var/www/cgi-bin/php-cgi-5.3.29
sudo chown -R www-data:www-data /var/www/cgi-bin
Step 7 – Configure Virtual Host of Apache

At last, we configure particular application via Virtual Host Configurations at Apache to use the PHPFarm and our certain version of PHP by editing /etc/apache2/sites-enabled/some-domain.conf

<VirtualHost *:80>
	DocumentRoot /home/websites/min-view-drupal
	ServerName minnehaha.com
	ServerAlias www.minnehaha.com
	#LogLevel debug
	#FastCgiServer /home/websites/cgi-bin/php-cgi-5.3.29
    	FastCgiServer /home/websites/cgi-bin/php-cgi-5.4.27
	ScriptAlias /cgi-bin-php/ /home/websites/cgi-bin/
	<Directory "/home/websites/min-view-drupal">
		Options Indexes MultiViews FollowSymLinks
		AllowOverride All
		Require all granted
		AddHandler php-cgi .php
		#Action php-cgi /cgi-bin-php/php-cgi-5.3.29
		Action php-cgi /cgi-bin-php/php-cgi-5.4.27
		<FilesMatch "\.php$">
                	SetHandler php-cgi
            	</FilesMatch>
	</Directory>
	<Directory "/home/websites/cgi-bin">
   		Order allow,deny
   		Allow from all 
  		Require all granted
	</Directory>
 	Errorlog "${APACHE_LOG_DIR}/virtual-hosts/minnehaha/error.txt"
	CustomLog "${APACHE_LOG_DIR}/virtual-hosts/minnehaha/customLog.txt" common
</VirtualHost>

Here, all the highlighted lines involve configuring the PHPFArm. The line 7,8 includes the PHPFarm service. The lines 13-18, enables the certain version for our application. The lines 20-24 enables apache server to read our mapping configuration file which should be moved to general Apache configuration script since this directory may be shared between other Virtual hosts. In short if you have multiple Virtual Hosts then the following should be moved into general to declare only once:

...
FastCgiServer /home/websites/cgi-bin/php-cgi-5.4.27
ScriptAlias /cgi-bin-php/ /home/websites/cgi-bin/
...
<Directory "/home/websites/cgi-bin">
   		Order allow,deny
   		Allow from all 
  		Require all granted
	</Directory>
...

At last, restart Apache to load our newest changes:

sudoe services apache2 restart
Step 8 – Test it

To test it, include the phpinfo command into the index.php file of the root dir(i.e./home/websites/min-view-drupal) of the application

<?php phpinfo();?>

This should display php version along other setting once pointing the browser to the application of virtual host configured above(i.e. minnehaha.com)

Switching PHP Versions

After compiling another version of PHP as we did in Step 4, the switching between PHP Versions is as easy as configuring apache virtual host to read another mapping as done in Step 8(see commented out php version 5.4.27) to point to another php version done by creating new mapping as done in Step 7.

Troubleshooting

1. client denied by server configuration:

This error we got when the location(i.e. /home/websites/cgi-bin) of our mapping script of step 7 wasn’t configured to be loaded by Apache in virtual host missing the following:

<Directory "/home/websites/cgi-bin">
   		Order allow,deny
   		Allow from all 
  		Require all granted
	</Directory>

By including the above snippet and restarting Apache, the problem was solved

2. FastCgiServer: redefinition of a previously defined FastCGI server phpFarm

This error appeared when I declared the following in multiple Virtual host configurations:

FastCgiServer /home/websites/cgi-bin/php-cgi-5.4.27
ScriptAlias /cgi-bin-php/ /home/websites/cgi-bin/

Once, I moved it out into the general apache configuration while commenting out all other instances, it solved the problem

Sources

  • https://github.com/cweiske/phpfarm
  • http://www.jabommi.de/wiki/downgrade-php-5-5-to-5-3-ubuntu-14-with-multiple-php-versions/
  • https://wiki.apache.org/httpd/PHP-FPM
  • https://www.howtoforge.com/how-to-use-multiple-php-versions-php-fpm-and-fastcgi-with-ispconfig-3-ubuntu-12.04-lts
  • http://geekpad.ca/blog/post/compiling-php-and-php-fpm-part-2
  • http://www.sitepoint.com/run-multiple-versions-php-one-server/
  • https://gist.github.com/amacgregor/11041627#file-custom-options-sh

Installing Apache on Mac/Linux

Mac comes with apache pre-installed, however. You may wish to install your own apache instance
http://margotskapacs.com/2013/09/installing-apache-on-mac/
Before start, make sure the default apache server is not running(see troubleshooting section below). To turn off, go to ‘System Preferences->Sharing’ and uncheck ‘Web Sharing’

Step 1. Installing Apache via macport

port selfupdate
sudo port install apache2

This installes Apache in /opt/local/apache2/ directory

Step 2. Configure Apache

Apache comes with sample configurations, lets copy it

sudo cp /opt/local/apache2/conf/httpd.conf.sample /opt/local/apache2/conf/httpd.conf

In the apache configuration file ../conf/httpd.conf change the following lines to specify root folder from where your websites is going to be serviced

...
<Directory "/opt/local/apache2/htdocs">
...
DocumentRoot "/opt/local/apache2/htdocs"

The path /opt[..]/htdocs’ can be anything you wish but in both places it have to point to the same folder

Next, add ‘index.php’ so that Apache grabs index.php file if present

<IfModule dir_module>
    DirectoryIndex index.html index.php
</IfModule>

Afterwards, configure Apache interpret all files ending with .php/.phps by adding these lines:

AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

Finally, to enable user directories uncomment:

Include conf/extra/httpd-userdir.conf

Step 3. Activate PHP module

After installing and compiling PHP, there is PHP package that Apache needs to load, so here how to activate it

cd /opt/local/apache2/modules
sudo /opt/local/apache2/bin/apxs -a -e -n "php5" libphp5.so
[activating module 'php5' in /opt/local/apache2/conf/httpd.conf] 

Step 4. Start Appache

To start and stop Apache:

sudo /opt/local/apache2/bin/apachectl start
sudo /opt/local/apache2/bin/apachectl stop

After starting, point your browser to ‘locahost’ and it should work. To test php, add the following file to the folder you specified ‘DocumentRoot’ in above:

<?php
phpinfo();
?>

Afterwards point to this file ‘localhost/fileName.php’ and it should display php configurations

Enable Virtual Hosting

To Enable virtual hosting, uncomment the following line in apache configuration file conf/httpd.conf

Include conf/extra/httpd-vhosts.conf

Afterwards, configure you virtual host at conf/extra/httpd-vhosts.conf. Here is an example to get you started:

NameVirtualHost *:80
...
<VirtualHost *:80>
    DocumentRoot "/path/to/your/site"
    ServerName domainName.com
    <Directory /path/to/your/site>
        Options FollowSymLinks
        AllowOverride All
        Allow from all
        Order Deny,Allow
    </Directory>
    ErrorLog "/private/var/log/apache2/domainName.com-error_log"
    CustomLog "/private/var/log/apache2/domainName.com-access_log" common
</VirtualHost>

Troubleshooting

1. To see Apache looaded configs:
httpd -V
//or for Debian servers
apache2ctl -V
2. To see if Apache deamon is running
ps -ef | grep httpd
3./.htaccess: Options not allowed here

This happen after specifying alias in the virtual host but never declaring directive:

     <Directory /path/to/the/alias>
        Options FollowSymLinks
        AllowOverride All
        Order Deny,Allow
        Allow from all
    </Directory>
    Alias /path /path/to/the/alias

So, by including the “<Directory..” gives the permissions for the .htaccess manage the ‘Options’ configuration solving the problem you see in the log

4. Virtual Hosting is Not Working

Make sure you have added "NameVirtualHost *:80" in one of the configurations that is being loaded such apache2.conf, some-v-host.conf,etc

5. client denied by server configuration (PHP FPM)

Make user to have Require all granted part of the Virtual Host configuration Directory section as following:

<Directory "/path/to/serving/dir">
		Options Indexes MultiViews FollowSymLinks
		AllowOverride All
		Order allow,deny
		Require all granted
	</Directory>
6. Forms Will not submit or “AH00128: File does not exist” in logs

The forms could be submitted and the apache logs were showing “AH00128: File does not exist[..]” for Apache 2.4. There issue is that mod_rewrite is not enabled by default. You can check if the mod_rewrite is enabled and loading by looking at phpinfo(). To enable mod_rewrite:

sudo a2enmod rewrite
sudo service apache2 restart

This will load mod_rewrite making the forms to Post for Drupal

caught SIGTERM, shutting down

This error was coming up for Apache 2.4 on Ubuntu after logging into Drupal. I am not sure which exactly fix it but did the following:

  • turn off limit for MaxKeepAliveRequests in the apache2.conf configuration file
  • Increase memory in php.ini by changing memory_limit
  • Increased max_input_time in php.ini
  • Increased max_execution_time in php.ini

In addition, it appears that apache restarts with the above error every time there is php syntax error.

Blank Screen

By default Apache will display blank screen when there is php error. To turn on errors to be displayed in browser instead of blank screen, edit php.ini as following:

display_errors=On
html_errors=On
error_reporting=E_ALL | E_STRICT 
display_startup_errors=On

This will enable error reporting in the browser. In case it doesn’t, then at your application level there must be ErrorHandler defined that hides all the errors. See more info here http://stackoverflow.com/questions/1475297/phps-white-screen-of-death

Troubleshooting Tip

When there is error, turn on max logging by changing ErrorLevel to trace8 in virtual host settings or Apache global settings:

...
 LogLevel trace8
 ErrorLog ${APACHE_LOG_DIR}/dev-virtual/error.log
..

Afterwards, tail the logs specified in ErrorLog from command line to follow real time Apache execution:

tail -f APACHE_LOG_DIR/dev-virtual/error.log

At last, make the requests and follow the logs in command line:

Useful Links

  • http://www.thegeekstuff.com/2008/08/9-tips-to-use-apachectl-and-httpd-like-a-power-user/
  • http://2tbsp.com/content/install_apache_2_and_php_5_macports