How to get Nightwatch tests running in CircleCI? - php

I am trying to get Nightwatch tests running in CircleCI and it has been a bit of a ...nightmare
It seems that CricleCI is not set up to run a webserver for a PHP app.
CircleCI version of the Chrome browser ~54 is not compatible with Nightwatch, which is asking for >= ~55
CircleCI's Chrome cannot find my local.webapp.dev domain, and gives the error ERR_ICANN_NAME_COLLISION
I have setup the web server, using the following apache config, modified from the recommended version in the CircleCI docs:
<VirtualHost *:80>
LoadModule php5_module /opt/circleci/php/5.6.17/libexec/apache2/libphp5.so
DocumentRoot /home/ubuntu/phpwebapp
ServerName local.webapp.dev
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
</VirtualHost>

After much trial and error, I finally have this working:
File examples:
circleApache.conf
circle.yaml
Nightwatch.json
package.json
The tests are run automatically by Circle using the package.json:
"test": "./node_modules/.bin/nightwatch --env circleci"
This picks up and runs the tests from your Nightwatch.json:
"circleci" : {
"output_folder" : "${CIRCLE_TEST_REPORTS}",
"launch_url" : "http://local.phpwebapp.dev",
"selenium_host" : "localhost",
"selenium_port" : 4444,
"screenshots" : {
"enabled" : false,
"path" : ""
},
"desiredCapabilities" : {
"browserName" : "chrome",
"marionette": true
}
}
CircleCI machines are using an older version of Chrome which is not compatible with the current version of Selenium/Nightwatch. Chrome needs to be updated in the pre dependencies of circle.yaml:
dependencies:
pre:
# Update Google Chrome.
- google-chrome --version
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
- sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb stable main" >> /etc/apt/sources.list.d/google.list'
- sudo apt-get update
- sudo apt-get --only-upgrade install google-chrome-stable
- google-chrome --version
The Circle docs forget an important piece in the apache conf file, you must set the allow/deny rules for your webroot directory, the port is also changed to use the default port 80:
<VirtualHost *:80>
LoadModule php5_module /opt/circleci/php/5.6.17/libexec/apache2/libphp5.so
DocumentRoot /home/ubuntu/phpwebapp
ServerName local.phpwebapp.dev
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
<Directory /home/ubuntu/phpwebapp>
AllowOverride all
Require all granted
</Directory>
</VirtualHost>
You must then activate all the required Apache modules and load your conf into Apache, using circle.yaml:
dependencies:
...
post:
# circle seems to expect this but doesnt install it
- sudo apt-get install libapache2-mod-php5
# copy apache config file
- sudo cp ~/phpwebapp/circleApache.conf /etc/apache2/sites-available
# give phpwebapp to apache
- sudo chown -R www-data:www-data ~/phpwebapp
- sudo a2enmod rewrite
- sudo a2enmod headers
- sudo a2ensite circleApache
# DocumentRoot doesnt work, so symlinking instead
- sudo rm -r /var/www/html
- sudo ln -s /home/ubuntu/phpwebapp /var/www/html
- ls /var/www/html
- sudo service apache2 restart
# add local.phpwebapp.dev to /etc/hosts
- sudo sh -c "echo 127.0.0.1 local.phpwebapp.dev >> /etc/hosts"
The a2enmod lines enable the necesary apache modules rewrite and header for the PHP app.
a2ensite enables the configuration file and your domain. Certain domains, like *.dev will also require adding a line to /etc/hosts:
- sudo sh -c "echo 127.0.0.1 local.phpwebapp.dev >> /etc/hosts"
This was realized when the Circle Chrome browser was giving the error ERR_ICANN_NAME_COLLISION. The error was uncovered by printing the source of the test page via Nightwatch:
browser
.url("http://www.local.phpwebapp.dev")
.source(function (result){
// Source will be stored in result.value
console.log(result.value);
})

Related

Apache + PHP (multi version) + multi sites (with different PHP versions) + user access setup

I was searching the internet looking for solution, unfortunately none of those was helpful.
I am trying to achive the following:
On Linux Ubuntu 20.04 setup several sites. Each site may have different PHP version. Also users of each site must not be able to read/write files on other sites. Each site should have own group/user.
I see the solution this way (and was trying this way):
to create different folders with different group/users (site1/site1, site2/site2)
install Apache, PHP as FCGI
enable MPM module to be able to run script on behalf of different user on each site
What I could do so far. I could install Apache + PHP (+FCGI) with different versions. So far it was ok, no problem.
Then I need to separate users I enabled MPM modules of Apache. The best result I could get is to run PHP script as if on behalf of different users. But when PHP script is trying to create a file in the same folder I can see the owner/group as www-data. So security issues are not resolved.
I not not sure that enabling MPM is working as it should.
Since there is a lot of work done, I didn't want to show all long list of commands here. I hope someone could advise the correct guide I could look at.
If not helpful I'll show all here
UPD 1: (I coudn't find a proper way to show code in reply comment, so I do this way)
sudo apt-get install apache2
sudo apt-get install php7.4
sudo apt-get install libapache2-mpm-itk
sudo useradd -m --shell /bin/bash --home /home/u-site1 u-site1
sudo passwd u-site1
sudo vi /etc/apache2/sites-available/site1.local.conf
-- start of content
<VirtualHost *:80>
ServerName site1.local
ServerAdmin info#site1.local
DocumentRoot /home/u-site1/site1.local/html
CustomLog ${APACHE_LOG_DIR}/site1.local.log combined
ErrorLog ${APACHE_LOG_DIR}/site1.local-error.log
<IfModule itk.c>
AssignUserID u-site1 u-site1
</IfModule>
<Directory "/home/u-site1/site1.local/html">
Options All -Indexes
AllowOverride All
Require all granted
Order allow,deny
allow from all
</Directory>
</VirtualHost>
-- end of content
sudo mkdir -p /home/u-site1/site1.local/html
sudo a2ensite site1.local.conf
sudo vi /home/u-site1/site1.local/html/index.php
-- start of content
site1.local
<?php
$sFilePath = __DIR__ . "/new.file";
$bRes = file_put_contents($sFilePath, "TEST");
if($bRes === false)
echo "<pre>", var_export(error_get_last(), 1), "</pre>";
phpinfo();
-- end of content
sudo chown -R u-site1:u-site1 /home/u-site1/site1.local
sudo chmod 755 /home/u-site1/site1.local
sudo systemctl restart apache2

Virtual hosts not working properly in ubuntu LAMP stack

I have created virtual hosts in the following ways:
Created laravel.test.conf as
- cd /etc/apache2/sites-available
- sudo nano laravel.test.conf
And then updated laravel.test.conf as
<VirtualHost *:80>
ServerName laravel.test
ServerAlias www.laravel.test
ServerAdmin admin#laravel.test
DocumentRoot /var/www/laravel/public
<Directory /var/www/laravel/public/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Run command: sudo a2ensite laravel.test
Permission provided:
sudo chown -R www-data: /var/www/laravel
sudo chown -R $USER:$USER /var/www/laravel
sudo chmod -R 755 /var/www
Added sitename on etc/hosts
127.0.0.1 laravel.test www.laravel.test
Reloaded apache sudo systemctl reload apache2
Run configtest sudo apachectl configtest and received Syntax Ok
Restarted apache server sudo systemctl restart apache2
Now, when I hit larave.test it loads the site successfully, but when ever I tried to hit any other route then it returns 404 error as shown in image.
This app is the freshly installed laravel one with laravel breeze so I am pretty much confident that there is a valide route. On top of that, if it was laravel, error, it would have been log it on app level and there would be different UI for 404 pages.
I have checked error log on laravel/storage/logs as well as apache2 logs on var/log/apache2/error.log but both of these logs file are empty.
Make sure your rewrite mod is enabled.
or simply run this in terminal
$ sudo a2enmod rewrite
$ sudo systemctl reload apache2

Run PHP application in Apache server using PHP-FPM

We have a php application which was running fine using
Docker Image :
php:7.2-apache-stretch
We now have to make use of the below image for better performance and make the application work as it was before .
php:7.2.17-fpm-stretch
As this image does not have apache in it . I updated the Dockerfile starting from the installation of apache2 and related packages based on various forums .
There is many other steps . I have just added the instructions which I have updated in the Dockerfile.
FROM php:7.2.17-fpm-stretch
RUN apt-get update && apt-get install -y apache2 wget
RUN cd /tmp && wget http://mirrors.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb && dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb;apt-get install -f
RUN a2enmod actions proxy_fcgi fastcgi
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
COPY info.php /var/www/html/info.php
COPY run.sh /app/run.sh
# EXPOSE 9000
RUN chmod 755 /app/run.sh
CMD "/app/run.sh"
The info.php contains <?php phpinfo( ); ?> . In the run.sh script , we start the php-fpm service and apache2 as below
php-fpm -D
/usr/sbin/apachectl -D FOREGROUND
previously I was trying to access the app from the port which was mapped to 9000 ( fpm ) . When I accessed the correct port where apache was running , I was able to view info.php .
The Content in the vhost.conf file.
<FilesMatch \.php$>
SetHandler "proxy:fcgi://localhost:9000"
</FilesMatch>
I got it working making a few modifications.
I used this slightly modified dockerfile:
FROM php:7.2.17-fpm-stretch
RUN apt-get update; apt-get install -y apache2 wget
RUN cd /tmp && wget http://mirrors.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb && dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb;apt-get install -f
RUN a2enmod actions proxy_fcgi fastcgi
COPY run.sh /app/run.sh
RUN chmod 755 /app/run.sh
CMD "/app/run.sh"
I also added the following snippet (the same modification you did) to /etc/apache2/sites-available/000-default.conf:
<FilesMatch \.php$>
SetHandler "proxy:fcgi://localhost:9000"
</FilesMatch>
Here is the output I get:
[09-Apr-2019 21:23:06] NOTICE: fpm is running, pid 9
[09-Apr-2019 21:23:06] NOTICE: ready to handle connections
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
Also, did you try building the dockerfile without the cache? Sometimes, caching can cause issues with package installation (see here for more details). To do a clean build of an image, just use:
docker build --no-cache
I got your new configuration working using this dockerfile:
FROM php:7.2.17-fpm-stretch
RUN apt-get update && apt-get install -y apache2 wget
RUN cd /tmp && wget http://mirrors.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb && dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb;apt-get install -f
RUN a2enmod actions proxy_fcgi fastcgi
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
COPY info.php /var/www/html/info.php
COPY run.sh /app/run.sh
RUN chmod 755 /app/run.sh
EXPOSE 80
CMD "/app/run.sh"
The command I ran was:
docker run -P -d --rm <php-image>
The exposed ports are:
0.0.0.0:32773->80/tcp, 0.0.0.0:32772->9000/tcp
I was able to access info.php using http://localhost:32773/info.php
I was able to access the php page . Everything was working fine . But I was looking in the wrong direction . When I run the container .
docker run -P -d --rm php:test-fpm
The output was
82071c9ff023 php:test-fpm "docker-php-entrypoi…" 2 seconds ago Up 1 second 0.0.0.0:32778->80/tcp, 0.0.0.0:32777->9000/tcp practical_mclean
I was accessing localhost:32777/info.php . But I should I accessed the 32778 where apache is exposed and localhost: 32778/info.php worked !!! .
Is there a way to avoid the port mapping of 9000. ???

Changing case of controller name

I have an application on my own computer (Kubuntu 13.10).
When I use separate class to define routes everything works perfect. For instance, I have url backend/dictionaries which handled by module backend, DictionariesController and indexAction. View for this url was at views/dictionaries/index.phtml.
Then I've switch to Phalcon\Mvc\Router\Annotations() and mount module's routes like $router->addModuleResource('backend', 'MyApp\Backend\Controller\Dictionaries');
Starting from that point my view does not rendered until I rename views/dictionaries to views/Dictionaries, with capital D.
However, when I've transfered project to production server (Debian 7) to see my views I had to rename view-folder back to lowercase.
So, on my computer action view lays in Controllername/acitonname.php (Dictionaries/index.php, for example) but on production it should be controllername/actionname.php (dictionaries/index.php)
I've printed controller name from dispatcher - on my machine it starts with capital letter but on production it is lowercase.
The question is why it is happend and how it can be fixed without handling 'dispatch:beforeDispatchLoop'?
ADDED:
The problem with development and production was in different phalcon version. On dev I use 1.2.4, on production - 1.2.3
But there are still bug (or feature) with route vs annotation routing definition. If I use annotation the controller name is Capitalized whereas if I use something like $route->add('/:controller/:action') definition the controller name is lowercase.
You face a century old problem: works at localhost but not on server. The solution is simple as use server environment for development.
For example I have 3 computers, one is Mac, one Windows and one God knows what. One day Ubuntu, another kubuntu or any other fancy named OS. If your server is Debian 7, no matter what OS you use at your working machine, your code always must be handled by Debian 7 and PHP configuration should be as close as your real machine's. Then you will not have such bugs like different paths to file, different end of line symbols and some other crazy stuff.
I suggest you trying Vagrant form https://www.vagrantup.com/downloads.html
You steps are like this:
Download https://www.virtualbox.org and install
Download https://www.vagrantup.com/downloads.html and install
Configure vagrant to your needs. Debian 7 with some php extensions or whatever you have at your production server.
Just navigate with terminal, command line or windows power shell to the directory where your vagrant file is and type "vagrant up --provision"
edit your main OS hosts file (on most linux should be here: /etc/hosts) add line: xxx.xxx.xx.xxx domain.vm (xxx.xxx.xxx.xxx - your virtual box ip address from vagrant config file. domain.vm is your domain which will work for your local development. enter anything you wish, i just like to use .vm tld for virtual machine)
now vagrant will read your config file, download needed virtual box, install php, keep in sync your main OS's folder with virtual box folder. You will edit your files as usual, vagrant will make sure, that on virtual box you have same files.
you should be able to go to http://domain.vm/ and see your site running on virtual machine with debian 7 locally on your kubuntu, windows, mac... OS. And what is the best thing - you don't have to worry about difference between OSs you use locally and on server.
Also if you would add all these things to git versioning, you would be able to work with any computer with your project under ±15 minutes (depends on internet speed to download 1 time virtual machine OS).
Maybe I should make a video tutorial on all this thing.. But you should be able to find one on Youtube.
Just to make your life easier, here's my working Vagrant config. I use ubuntu + PhalconPHP framework + MongoDb and Mysql. There are 2 files. One for vagrant main things: download OS, mount sync folder etc, and one - for installation after starting vagrant. If you want to rerun installation script, just type vagrant provision
Vagrantfile file (name of the file is just "Vagrantfile")
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Base Box
# --------------------
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
# Connect to IP
# --------------------
config.vm.network :private_network, ip: "192.168.5.0"
# Forward to Port
# --------------------
#config.vm.network :forwarded_port, guest: 80, host: 8080
# Optional (Remove if desired)
config.vm.provider :virtualbox do |v|
# How much RAM to give the VM (in MB)
# -----------------------------------
v.customize ["modifyvm", :id, "--memory", "700"]
# Uncomment the Bottom two lines to enable muli-core in the VM
#v.customize ["modifyvm", :id, "--cpus", "2"]
#v.customize ["modifyvm", :id, "--ioapic", "on"]
end
# Provisioning Script
# --------------------
config.vm.provision "shell", path: "init.sh"
# Synced Folder
# --------------------
config.vm.synced_folder "./", "/var/www/", :mount_options => [ "dmode=775", "fmode=644" ], :owner => 'www-data', :group => 'www-data'
end
and the installation file (name of the file is "init.sh"):
#!/bin/bash
# Using Precise32 Ubuntu
# to use closest ubuntu mirror by geographic location
echo 'deb mirror://mirrors.ubuntu.com/mirrors.txt precise main restricted universe multiverse' | cat - /etc/apt/sources.list > temp && mv temp /etc/apt/sources.list
echo 'deb mirror://mirrors.ubuntu.com/mirrors.txt precise-updates main restricted universe multiverse' | cat - /etc/apt/sources.list > temp && mv temp /etc/apt/sources.list
echo 'deb mirror://mirrors.ubuntu.com/mirrors.txt precise-backports main restricted universe multiverse' | cat - /etc/apt/sources.list > temp && mv temp /etc/apt/sources.list
echo 'deb mirror://mirrors.ubuntu.com/mirrors.txt precise-security main restricted universe multiverse' | cat - /etc/apt/sources.list > temp && mv temp /etc/apt/sources.list
sudo apt-get update
sudo apt-get update
#
# For PHP 5.5
#
sudo apt-get install -y python-software-properties
sudo add-apt-repository ppa:ondrej/php5
sudo apt-get update
#
# MySQL with root:<no password>
#
export DEBIAN_FRONTEND=noninteractive
apt-get -q -y install mysql-server
#
# PHP
#
sudo apt-get install -y php5 php5-dev apache2 libapache2-mod-php5 php5-mysql php5-curl php5-mcrypt php5-gd php5-imagick
#
# Redis
#
sudo apt-get install -y redis-server
#
# MongoDB
#
sudo apt-get install mongodb-clients mongodb-server
#
# Utilities
#
sudo apt-get install -y curl htop git-core gcc autoconf
sudo apt-get install -y libpcre3-dev
#
# Redis Configuration
# Allow us to Remote from Vagrant with Port
#
sudo cp /etc/redis/redis.conf /etc/redis/redis.bkup.conf
sudo sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
sudo /etc/init.d/redis-server restart
#
# MySQL Configuration
# Allow us to Remote from Vagrant with Port
#
sudo cp /etc/mysql/my.cnf /etc/mysql/my.bkup.cnf
# Note: Since the MySQL bind-address has a tab character I comment out the end line
sudo sed -i 's/bind-address/bind-address = 0.0.0.0#/' /etc/mysql/my.cnf
#
# Grant All Priveleges to ROOT for remote access
#
mysql -u root -Bse "GRANT ALL PRIVILEGES ON *.* TO 'root'#'%' IDENTIFIED BY '' WITH GRANT OPTION;"
sudo service mysql restart
#
# Composer for PHP
#
sudo curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
#
# Apache VHost
#
cd ~
echo '<VirtualHost *:80>
DocumentRoot /var/www/public
SetEnv APPLICATION_ENV "development"
</VirtualHost>
<Directory "/var/www/public">
Options Indexes Followsymlinks
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/www/logs/error.log
' > vagrant.conf
sudo mv vagrant.conf /etc/apache2/sites-available
sudo a2enmod rewrite
#
# Install PhalconPHP
# Enable it
#
cd ~
git clone --depth=1 git://github.com/phalcon/cphalcon.git
cd cphalcon/build
sudo ./install
echo "extension=phalcon.so" > phalcon.ini
sudo mv phalcon.ini /etc/php5/mods-available
sudo php5enmod phalcon
sudo php5enmod curl
#
# Install PhalconPHP DevTools
#
cd ~
echo '{"require": {"phalcon/devtools": "dev-master"}}' > composer.json
composer install
rm composer.json
sudo mkdir /opt/phalcon-tools
sudo mv ~/vendor/phalcon/devtools/* /opt/phalcon-tools
sudo ln -s /opt/phalcon-tools/phalcon.php /usr/bin/phalcon
sudo rm -rf ~vendor
#
# PHP.ini params edits
#
sudo echo "; ######### PHP.ini modifications from vagrant init.sh #######" >> /etc/php5/apache2/php.ini
sudo echo "error_reporting = E_ALL | E_STRICT" >> /etc/php5/apache2/php.ini
sudo echo "display_errors = On" >> /etc/php5/apache2/php.ini
#
# Reload apache
#
sudo a2ensite vagrant
sudo a2dissite 000-default
sudo service apache2 reload
sudo service apache2 restart
sudo service mongodb restart
#echo -e "----------------------------------------"
#echo -e "To create a Phalcon Project:\n"
#echo -e "----------------------------------------"
#echo -e "$ cd /var/www"
#echo -e "$ phalcon project projectname\n"
#echo -e
#echo -e "Then follow the README.md to copy/paste the VirtualHost!\n"
#echo -e "----------------------------------------"
#echo -e "Default Site: http://192.168.5.0"
#echo -e "----------------------------------------"
####### writable Volt directory
sudo mkdir /vagrant/cache/volt/
sudo chmod 777 /vagrant/cache/volt/
Of course if you need Debian 7, installation script should be adapted to your needs and edit Vagrantfile lines about ubuntu to your OS. Here is the list of all supported OS's: http://www.vagrantbox.es
Change these two lines in Vagrant file:
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
And also change install script, i don't use Debian, can't tell what can go wrong.

How can one run multiple versions of PHP 5.x on a development LAMP server?

I need to test my PHP applications with multiple versions of PHP 5.x, such as PHP 5.0.0 and PHP 5.2.8.
Is there a way that I can configure a development LAMP server so I can quickly test applications with multiple versions of PHP5?
With CentOS, you can do it using a combination of fastcgi for one version of PHP, and php-fpm for the other, as described here:
https://web.archive.org/web/20130707085630/http://linuxplayer.org/2011/05/intall-multiple-version-of-php-on-one-server
Based on CentOS 5.6, for Apache only
1. Enable rpmforge and epel yum repository
wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm
wget http://download.fedora.redhat.com/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
sudo rpm -ivh rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm
sudo rpm -ivh epel-release-5-4.noarch.rpm
2. Install php-5.1
CentOS/RHEL 5.x series have php-5.1 in box, simply install it with yum, eg:
sudo yum install php php-mysql php-mbstring php-mcrypt
3. Compile and install php 5.2 and 5.3 from source
For php 5.2 and 5.3, we can find many rpm packages on the Internet. However, they all conflict with the php which comes with CentOS, so, we’d better build and install them from soure, this is not difficult, the point is to install php at different location.
However, when install php as an apache module, we can only use one version of php at the same time. If we need to run different version of php on the same server, at the same time, for example, different virtual host may need different version of php. Fortunately, the cool FastCGI and PHP-FPM can help.
Build and install php-5.2 with fastcgi enabled
1) Install required dev packages
yum install gcc libxml2-devel bzip2-devel zlib-devel \
curl-devel libmcrypt-devel libjpeg-devel \
libpng-devel gd-devel mysql-devel
2) Compile and install
wget http://cn.php.net/get/php-5.2.17.tar.bz2/from/this/mirror
tar -xjf php-5.2.17.tar.bz2
cd php-5.2.17
./configure --prefix=/usr/local/php52 \
--with-config-file-path=/etc/php52 \
--with-config-file-scan-dir=/etc/php52/php.d \
--with-libdir=lib64 \
--with-mysql \
--with-mysqli \
--enable-fastcgi \
--enable-force-cgi-redirect \
--enable-mbstring \
--disable-debug \
--disable-rpath \
--with-bz2 \
--with-curl \
--with-gettext \
--with-iconv \
--with-openssl \
--with-gd \
--with-mcrypt \
--with-pcre-regex \
--with-zlib
make -j4 > /dev/null
sudo make install
sudo mkdir /etc/php52
sudo cp php.ini-recommended /etc/php52/php.ini
3) create a fastcgi wrapper script
create file /usr/local/php52/bin/fcgiwrapper.sh
#!/bin/bash
PHP_FCGI_MAX_REQUESTS=10000
export PHP_FCGI_MAX_REQUESTS
exec /usr/local/php52/bin/php-cgi
chmod a+x /usr/local/php52/bin/fcgiwrapper.sh
Build and install php-5.3 with fpm enabled
wget http://cn.php.net/get/php-5.3.6.tar.bz2/from/this/mirror
tar -xjf php-5.3.6.tar.bz2
cd php-5.3.6
./configure --prefix=/usr/local/php53 \
--with-config-file-path=/etc/php53 \
--with-config-file-scan-dir=/etc/php53/php.d \
--enable-fpm \
--with-fpm-user=apache \
--with-fpm-group=apache \
--with-libdir=lib64 \
--with-mysql \
--with-mysqli \
--enable-mbstring \
--disable-debug \
--disable-rpath \
--with-bz2 \
--with-curl \
--with-gettext \
--with-iconv \
--with-openssl \
--with-gd \
--with-mcrypt \
--with-pcre-regex \
--with-zlib
make -j4 && sudo make install
sudo mkdir /etc/php53
sudo cp php.ini-production /etc/php53/php.ini
sed -i -e 's#php_fpm_CONF=\${prefix}/etc/php-fpm.conf#php_fpm_CONF=/etc/php53/php-fpm.conf#' \
sapi/fpm/init.d.php-fpm
sudo cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
sudo chmod a+x /etc/init.d/php-fpm
sudo /sbin/chkconfig --add php-fpm
sudo /sbin/chkconfig php-fpm on
sudo cp sapi/fpm/php-fpm.conf /etc/php53/
Configue php-fpm
Edit /etc/php53/php-fpm.conf, change some settings. This step is mainly to uncomment some settings, you can adjust the value if you like.
pid = run/php-fpm.pid
listen = 127.0.0.1:9000
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
Then, start fpm
sudo /etc/init.d/php-fpm start
Install and setup mod_fastcgi, mod_fcgid
sudo yum install libtool httpd-devel apr-devel
wget http://www.fastcgi.com/dist/mod_fastcgi-current.tar.gz
tar -xzf mod_fastcgi-current.tar.gz
cd mod_fastcgi-2.4.6
cp Makefile.AP2 Makefile
sudo make top_dir=/usr/lib64/httpd/ install
sudo sh -c "echo 'LoadModule fastcgi_module modules/mod_fastcgi.so' > /etc/httpd/conf.d/mod_fastcgi.conf"
yum install mod_fcgid
Setup and test virtual hosts
1) Add the following line to /etc/hosts
127.0.0.1 web1.example.com web2.example.com web3.example.com
2) Create web document root and drop an index.php under it to show phpinfo
switch to user root, run
mkdir /var/www/fcgi-bin
for i in {1..3}; do
web_root=/var/www/web$i
mkdir $web_root
echo "<?php phpinfo(); ?>" > $web_root/index.php
done
Note: The empty /var/www/fcgi-bin directory is required, DO NOT REMOVE IT LATER
3) Create Apache config file(append to httpd.conf)
NameVirtualHost *:80
# module settings
# mod_fcgid
<IfModule mod_fcgid.c>
idletimeout 3600
processlifetime 7200
maxprocesscount 17
maxrequestsperprocess 16
ipcconnecttimeout 60
ipccommtimeout 90
</IfModule>
# mod_fastcgi with php-fpm
<IfModule mod_fastcgi.c>
FastCgiExternalServer /var/www/fcgi-bin/php-fpm -host 127.0.0.1:9000
</IfModule>
# virtual hosts...
#################################################################
#1st virtual host, use mod_php, run php-5.1
#################################################################
<VirtualHost *:80>
ServerName web1.example.com
DocumentRoot "/var/www/web1"
<ifmodule mod_php5.c>
<FilesMatch \.php$>
AddHandler php5-script .php
</FilesMatch>
</IfModule>
<Directory "/var/www/web1">
DirectoryIndex index.php index.html index.htm
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
#################################################################
#2nd virtual host, use mod_fcgid, run php-5.2
#################################################################
<VirtualHost *:80>
ServerName web2.example.com
DocumentRoot "/var/www/web2"
<IfModule mod_fcgid.c>
AddHandler fcgid-script .php
FCGIWrapper /usr/local/php52/bin/fcgiwrapper.sh
</IfModule>
<Directory "/var/www/web2">
DirectoryIndex index.php index.html index.htm
Options -Indexes FollowSymLinks +ExecCGI
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
#################################################################
#3rd virtual host, use mod_fastcgi + php-fpm, run php-5.3
#################################################################
<VirtualHost *:80>
ServerName web3.example.com
DocumentRoot "/var/www/web3"
<IfModule mod_fastcgi.c>
ScriptAlias /fcgi-bin/ /var/www/fcgi-bin/
AddHandler php5-fastcgi .php
Action php5-fastcgi /fcgi-bin/php-fpm
</IfModule>
<Directory "/var/www/web3">
DirectoryIndex index.php index.html index.htm
Options -Indexes FollowSymLinks +ExecCGI
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
4) restart apache. visit the 3 sites respectly to view phpinfo and validate the result. ie:
http://web1.example.com
http://web2.example.com
http://web3.example.com
If all OK, you can use one of the 3 virtual host as template to create new virtual host, with the desired php version.
One way to do this is to have your main version of php set up with mod_php and run all of the others through fast cgi on different ports (i.e. 81, 82, 83 etc). This won't guarantee totally consistent behavior though.
Having multiple instances of apache + php never really tickled my fancy, but it probably the easiest way to do it. If you don't feel like KISS ... here's an idea.
Get your apache up and running, and try do configure it like debian and ubuntu do it, eg, have directories for loaded modules. Your apache conf can use lines like this:
Include /etc/apache2/mods-enabled/*.load
Include /etc/apache2/mods-enabled/*.conf
Then build your first version of php, and give it a prefix that has the version number explicitly contained, eg, /usr/local/php/5.2.8, /usr/local/php/5.2.6 ...
The conf/load would look something like this:
php5.2.6.load
LoadModule php5_module /usr/local/php/5.2.6/libphp5.so
php5.2.8.load
LoadModule php5_module /usr/local/php/5.2.8/libphp5.so
To switch versions, all you have to do is change the load and conf files from the directory apache does the include on for the ones for another version. You can automate that with a simple bash script (delete the actual file, copy the alternate versions file in place, and restart apache.
One advantage of this setup is the everything is consitent, so long you keep the php.ini's the same in terms of options and modules (which you would have to do with CGI anyway). They're all going through SAPI. Your applications won't need any changes whatsoever, nor need to use relative URLs.
I think this should work, but then again, i haven't tried it, nor am i likely to do so as i don't have the same requirements as you. Do comment if you ever do try though.
Note: The following method will work on windows.
An alternative method (if it is ok to run a single version of PHP at a time) is to define multiple Apache services, each of which will use a different PHP version.
First of all use conditions in the Apache configuration file:
<ifdefine php54>
SetEnv PHPRC C:/apache/php54/
ScriptAlias /php/ "C:/apache/php54/"
AddType application/x-httpd-php .php
Action application/x-httpd-php "/php/php-cgi.exe"
</ifdefine>
<ifdefine php55>
SetEnv PHPRC C:/apache/php55/
ScriptAlias /php/ "C:/apache/php55/"
AddType application/x-httpd-php .php
Action application/x-httpd-php "/php/php-cgi.exe"
</ifdefine>
Now using the httpd.exe create two separate services from command line (elevated to administrator):
httpd.exe -k install -n Apache224_php54 -D php54
httpd.exe -k install -n Apache224_php55 -D php55
Now you can start one of the above services at a time (should shutdown one before starting the other).
If you have previously installed Apache as service you can remove that using below command (replace the service name with the one you have used):
apache -k uninstall -n Apache224
One further note is that I personally use a "notification area icon program" called "Seobiseu" to start and stop services as needed. I have added the two above services to it.
Understanding that you're probably talking about a local/desktop machine and would probably like to continue talking about a local/desktop machine, I'll throw an alternative out there for you just in case it might help you or someone else:
Set up multiple virtual server instances in the cloud, and share your code between them as a git repository (or mercurial, I suppose, though I have no personal experience all you really need is something decentralized). This has the benefit of giving you as close to a production experience as possible, and if you have experience setting up servers then it's not that complicated (or expensive, if you just want to spin a server up, do what you need to do, then spin it down again, then you're talking about a few cents up to say 50 cents, up to a few bucks if you just leave it running).
I do all of my project development in the cloud these days and I've found it much simpler to manage the infrastructure than I ever did when using local/non-virtualized installs, and it makes this sort of side-by-side scenario fairly straight forward. I just wanted to throw the idea out there if you hadn't considered it.
I have just successfully downgraded from PHP5.3 on Ubuntu 10.
To do this I used the following script:
#! /bin/sh
php_packages=`dpkg -l | grep php | awk '{print $2}'`
sudo apt-get remove $php_packages
sed s/lucid/karmic/g /etc/apt/sources.list | sudo tee /etc/apt/sources.list.d/karmic.list
sudo mkdir -p /etc/apt/preferences.d/
for package in $php_packages;
do echo "Package: $package
Pin: release a=karmic
Pin-Priority: 991
" | sudo tee -a /etc/apt/preferences.d/php
done
sudo apt-get update
sudo apt-get install $php_packages
For anyone that doesn't know how to run scripts from the command line, here is a brief tutorial:
1. cd ~/
2. mkdir bin
3. sudo nano ~/bin/myscriptname.sh
4. paste in the script code I have posted above this
5. ctrl+x (this exits and prompts for you to save)
6. chmod u+x myscriptname.sh
These 6 steps create a script in a folder called "bin" in your home directory. You can then run this script by calling the following command:
~/bin/myscriptname.sh
Oulia!
Hope this helps some of you!
For reference, here is where I got the script:
PHP5.2.10 for Ubuntu 10
There are several people on there all confirming that this works, and it worked a treat for me.
Rasmus Lerdorf, who created PHP, is maintaining an active Vagrant solution that seems to solve your needs. It allows for quickly switching between PHP versions, currently supporting more than 20 different versions. It comes out of the box with an nginx server, but can easily be switched to apache2 with a preconfigured setting. It also supports MySQL out of the box.
This way you will have access to all versions of PHP, deployable on two of the main web servers, in a nice vagrant box, maintained by the big man behind PHP.
For more information I would like to refer to the talk given by mr. Lerdorf at https://youtu.be/6XnysJAyThs?t=2864
The github repository containing the Vagrant solution is found at https://github.com/rlerdorf/php7dev
I have several projects running on my box. If you have already installed more than one version, this bash script should help you easily switch. At the moment I have php5, php5.6, and php7.0 which I often swtich back and forth depending on the project I am working on. Here is my code.
Feel free to copy. Make sure you understand how the code works. This is for the webhostin. my local box my mods are stored at /etc/apache2/mods-enabled/
#!/bin/bash
# This file is for switching php versions.
# To run this file you must use bash, not sh
#
# OS: Ubuntu 14.04 but should work on any linux
# Example: bash phpswitch.sh 7.0
# Written by Daniel Pflieger
# growlingflea at g mail dot com
NEWVERSION=$1 #this is the git directory target
#get the active php enabled mod by getting the array of files and store
#it to a variable
VAR=$(ls /etc/apache2/mods-enabled/php*)
#parse the returned variables and get the version of php that is active.
IFS=' ' read -r -a array <<< "$VAR"
array[0]=${array[0]#*php}
array[0]=${array[0]%.conf}
#confirm that the newversion veriable isn't empty.. if it is tell user
#current version and exit
if [ "$NEWVERSION" = "" ]; then
echo current version is ${array[0]}. To change version please use argument
exit 1
fi
OLDVERSION=${array[0]}
#confirm to the user this is what they want to do
echo "Update php" ${OLDVERSION} to ${NEWVERSION}
#give the user the opportunity to use CTRL-C to exit ot just hit return
read x
#call a2dismod function: this deactivate the current php version
sudo a2dismod php${OLDVERSION}
#call the a2enmod version. This enables the new mode
sudo a2enmod php${NEWVERSION}
echo "Restart service??"
read x
#restart apache
sudo service apache2 restart
For testing I just run multiple instances of httpd on different IP addresses, so I have php7 running on 192.168.0.70 and php5.6 running on 192.168.0.56. In production I have a site running an old oscommerce running php5.3 and I just have a different conf file for the site
httpd -f /etc/apache2/php70.conf
httpd -f /etc/apache2/php53.conf
It's also a clean way to have different php.ini files for different sites. If you just have a couple of sites if a nice way to keep things organized and you don't have to worry about more then 1 site at a time when you upgrade something

Categories