PHP5 and PHP7 on Linux

Who is this for?

  • Linux user
  • Prefer to compile official php7 source code rather than use a docker container or a ppa
  • Want to have both php5 and php7 installed on your system switching between them easily
  • Want to run php5 and php7 on nginx at the same time

Time to cook...

This recipe is a compilation of different tutorials I've found over the Internet. I just added some fancy features and tuned the procedure up to make it work as I expected. However, what you are about to read wouldn't be possible without them, so thanks so much:

Tested on Ubuntu 15.10 and Elementary OS Freya.

Prerequisites

First of all, be root my friend!

sudo su -  
Packages
apt-get -y install build-essential autoconf insserv bison git  
Libraries
apt-get -y install libgmp-dev libmysqlclient-dev libfcgi-dev libfcgi0ldbl libmcrypt-dev  
PHP5

If you have php5 already installed skip this step

apt-get -y install php5 php5-fpm php5-memcached php5-intl php5-mcrypt php5-xdebug php5-mysql  
MySQL and Nginx

If you have them already installed or you just don't need them skip this step

apt-get -y install mysql-server mysql-client nginx  
Fix gmp
ln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/include/gmp.h  
Php build dependencies

To be able to compile php7 you must add php5 build dependencies

apt-get -y build-dep php5  

php5, it's ok, it's not a mistake

Compiling php7

Now you are about to clone official php7 source code. Feel free to choose the path you want.

Clone repository
git clone https://git.php.net/repository/php-src.git  
cd php-src  
Compile
./buildconf
./configure --prefix=/usr/local/php7 --localstatedir=/usr/local/var --sysconfdir=/usr/local/etc/php7 --with-config-file-path=/usr/local/etc/php7 --with-config-file-scan-dir=/usr/local/etc/php7/conf.d --mandir=/usr/local/php7/share/man --enable-mbstring --enable-zip --enable-bcmath --enable-pcntl --enable-ftp --enable-exif --enable-calendar --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-wddx --with-curl --with-mcrypt --with-iconv --with-gmp --with-pspell --with-gd --with-jpeg-dir=/usr --with-png-dir=/usr --with-zlib-dir=/usr --with-xpm-dir=/usr --with-freetype-dir=/usr --enable-gd-native-ttf --enable-gd-jis-conv --with-openssl --with-pdo-mysql=/usr --with-gettext=/usr --with-zlib=/usr --with-bz2=/usr --with-recode=/usr --with-mysqli=/usr/bin/mysql_config --with-fpm-user=www-data --with-fpm-group=www-data --enable-fpm --enable-sockets --enable-intl
make  
make install  

Configuring php7

Now you are going to configure php7. Remember the path where you cloned php7 source code to.

php.ini
cp <path_to_php7_source_code>/php.ini-production /usr/local/etc/php7/php.ini  
php-fpm.conf
cp /usr/local/etc/php7/php-fpm.conf.default /usr/local/etc/php7/php-fpm.conf  

Edit following file

/usr/local/etc/php7/php-fpm.conf 

add/edit following line

pid = run/php-fpm.pid  
www.conf
cp /usr/local/etc/php7/php-fpm.d/www.conf.default /usr/local/etc/php7/php-fpm.d/www.conf  

Edit following file

/usr/local/etc/php7/php-fpm.d/www.conf

add/edit following lines

;listen = 127.0.0.1:9000
listen = /var/run/php7-fpm.sock  
listen.owner = www-data  
listen.group = www-data  
listen.mode = 0660  

Service scripts

php7-fpm

Create following file

/etc/init.d/php7-fpm
#! /bin/sh
### BEGIN INIT INFO
# Provides:          php7-fpm
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts php7-fpm
# Description:       starts the PHP FastCGI Process Manager daemon
### END INIT INFO
php_fpm_BIN=/usr/local/php7/sbin/php-fpm  
php_fpm_CONF=/usr/local/etc/php7/php-fpm.conf  
php_fpm_PID=/usr/local/var/run/php-fpm.pid  
php_opts="--fpm-config $php_fpm_CONF"  
wait_for_pid () {  
        try=0
        while test $try -lt 35 ; do
                case "$1" in
                        'created')
                        if [ -f "$2" ] ; then
                                try=''
                                break
                        fi
                        ;;
                        'removed')
                        if [ ! -f "$2" ] ; then
                                try=''
                                break
                        fi
                        ;;
                esac
                echo -n .
                try=`expr $try + 1`
                sleep 1
        done
}
case "$1" in  
        start)
                echo -n "Starting php-fpm "
                $php_fpm_BIN $php_opts
                if [ "$?" != 0 ] ; then
                        echo " failed"
                        exit 1
                fi
                wait_for_pid created $php_fpm_PID
                if [ -n "$try" ] ; then
                        echo " failed"
                        exit 1
                else
                        echo " done"
                fi
        ;;
        stop)
                echo -n "Gracefully shutting down php-fpm "
                if [ ! -r $php_fpm_PID ] ; then
                        echo "warning, no pid file found - php-fpm is not running ?"
                        exit 1
                fi
                kill -QUIT `cat $php_fpm_PID`
                wait_for_pid removed $php_fpm_PID
                if [ -n "$try" ] ; then
                        echo " failed. Use force-exit"
                        exit 1
                else
                        echo " done"
                       echo " done"
                fi
        ;;
        force-quit)
                echo -n "Terminating php-fpm "
                if [ ! -r $php_fpm_PID ] ; then
                        echo "warning, no pid file found - php-fpm is not running ?"
                        exit 1
                fi
                kill -TERM `cat $php_fpm_PID`
                wait_for_pid removed $php_fpm_PID
                if [ -n "$try" ] ; then
                        echo " failed"
                        exit 1
                else
                        echo " done"
                fi
        ;;
        restart)
                $0 stop
                $0 start
        ;;
        reload)
                echo -n "Reload service php-fpm "
                if [ ! -r $php_fpm_PID ] ; then
                        echo "warning, no pid file found - php-fpm is not running ?"
                        exit 1
                fi
                kill -USR2 `cat $php_fpm_PID`
                echo " done"
        ;;
        *)
                echo "Usage: $0 {start|stop|force-quit|restart|reload}"
                exit 1
        ;;
esac  
php7-fpm permissions
chmod 755 /etc/init.d/php7-fpm  
php7-fpm enable
/usr/lib/insserv/insserv php7-fpm
php7-fpm.service

Create following file

/lib/systemd/system/php7-fpm.service
[Unit]
Description=The PHP 7 FastCGI Process Manager  
After=network.target

[Service]
Type=simple  
PIDFile=/usr/local/var/run/php-fpm.pid  
ExecStart=/usr/local/php7/sbin/php-fpm --nodaemonize --fpm-config /usr/local/etc/php7/php-fpm.conf  
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target  
Start php7-fpm service

If you system supports systemctl then run following commands

systemctl enable php7-fpm.service  
systemctl daemon-reload  
service php7-fpm start  

If not, just run command below

/etc/init.d/php7-fpm start
Socket owner
chown www-data. /var/run/php7-fpm.sock  

You can configure php5 and php7 in different nginx virtual hosts at this moment. Just follow these steps

Add hosts

Edit hosts file

/etc/hosts

Add following line

127.0.0.1 php5 php7  
Add nginx virtual hosts

php5

server {  
    listen *:80;
    root /var/www/html;
    index index.php index.html index.htm index.nginx-debian.html;
    server_name php5;
    location / {
        try_files $uri $uri/ =404;
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
    }
}

php7

server {  
    listen *:80;
    root /var/www/html;
    index index.php index.html index.htm index.nginx-debian.html;
    server_name php7;
    location / {
        try_files $uri $uri/ =404;
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php7-fpm.sock;
    }
}
Add phpinfo

Create index.php

/var/www/html/index.php
<?php  
phpinfo();  
?>

Restart nginx and try following urls on your browser:

Switch between php5 and php7

Despite of nginx can run on php5 and php7 sockets, to set php system running version (cli) follow these steps

Add php7 as an alternative
update-alternatives --install "/usr/bin/php" "php" "/usr/local/php7/bin/php" 1  
Configure system php version

You can select system php version by running command below. You'll be asked to choose between available options, select php5 or php7

update-alternatives --config php  
Check php version
php -v  

And that's all folks!