如何在开发LAMP服务器上运行多个版本的PHP 5.x?

81

我需要使用多个PHP 5.x版本(例如PHP 5.0.0和PHP 5.2.8)测试我的PHP应用程序。

是否有一种方法可以配置开发用的LAMP服务器,以便快速测试使用多个PHP5版本的应用程序?


你应该能够使用PATH变量,但我不能保证100%,所以我不会回答以获取声望。 - Malfist
如何在ISPConfig 3(Ubuntu 12.10)中使用多个PHP版本(PHP-FPM和FastCGI)
  • @hek2mgl:有关开发工具的问题不是离题。
- hakre
@hakre 同意,使用FPM可以减少在作为Apache模块加载时多个版本相互影响的可能性 :) - Ja͢ck
@Jack:啊,不是Apache模块,是FCGI ;) - hakre
到目前为止,我已经尝试过 phpbrewphp-version,但它们似乎都无法编译 PHP。 - nice ass
9个回答

24
使用CentOS,您可以通过结合快速cgi和php-fpm来使用两个不同的PHP版本,具体方法在此处描述:https://web.archive.org/web/20130707085630/http://linuxplayer.org/2011/05/intall-multiple-version-of-php-on-one-server 基于仅适用于Apache的CentOS 5.6:
1. 启用rpmforge和epel yum仓库
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. 安装 php-5.1

CentOS/RHEL 5.x 系列已经预装了 php-5.1,只需使用 yum 命令安装即可,例如:

sudo yum install php php-mysql php-mbstring php-mcrypt

3. 从源代码编译并安装 PHP 5.2 和 5.3

对于 PHP 5.2 和 5.3,我们可以在互联网上找到很多 RPM 包。然而,它们都会与 CentOS 自带的 PHP 冲突,因此,我们最好从源代码构建和安装它们。这并不难,关键是要将 PHP 安装在不同的位置。

但是,当将 PHP 安装为 Apache 模块时,我们只能同时使用一个版本的 PHP。如果我们需要在同一台服务器上运行不同版本的 PHP,并且在同一时间内运行,例如,不同的虚拟主机可能需要不同版本的 PHP。幸运的是,酷炫的 FastCGI 和 PHP-FPM 可以帮助实现。

构建并安装启用 FastCGI 的 PHP-5.2:

1)安装所需的开发包

yum install gcc libxml2-devel bzip2-devel zlib-devel \
    curl-devel libmcrypt-devel libjpeg-devel \
    libpng-devel gd-devel mysql-devel

2) 编译和安装

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) 创建一个 FastCGI 包装脚本

创建文件 /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/

配置php-fpm

编辑/etc/php53/php-fpm.conf文件,更改一些设置。这一步的主要目的是取消注释某些设置,如果需要,您可以调整其值。

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

然后,启动fpm

sudo /etc/init.d/php-fpm start

安装和配置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

设置和测试虚拟主机

1) 将以下行添加到 /etc/hosts 文件中

127.0.0.1 web1.example.com web2.example.com web3.example.com

2) 创建Web文档根目录,并在其中放置一个index.php文件以显示phpinfo。 切换到root用户,运行以下命令:

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
注意:空的 /var/www/fcgi-bin 目录是必需的,以后不要删除它。

3) 创建 Apache 配置文件(追加到 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)重新启动Apache。分别访问3个站点以查看phpinfo并验证结果。例如:

http://web1.example.com
http://web2.example.com
http://web3.example.com

如果一切正常,您可以使用其中一个虚拟主机作为模板来创建新的虚拟主机,并选择所需的PHP版本。


1
这是一种仅提供链接的回答。请在回答中包含相关细节,而不完全依赖其他站点。链接有一个恼人的问题,那就是它们可能会消失,这样SO仍然不包含相关信息。 - Maarten Bodewes
你可能想要了解一下CloudLinux。它是一个付费的解决方案,但价格还算合理。 - transilvlad
1
回答正确!这里是Ubuntu的相同解决方案:https://www.howtoforge.com/how-to-use-multiple-php-versions-php-fpm-and-fastcgi-with-ispconfig-3-ubuntu-13.04 - Tobias Gaertner

17

有一种方法是使用mod_php设置主版本的php,并通过不同端口(例如81、82、83等)在fastcgi中运行所有其他版本。但这并不能完全保证一致的行为。


32
一个想法:对于 PHP 5.2.1,使用端口号 10521。对于 5.0.0 版本,使用 10500 :) - Wayne
2
另一个选择是在不同的路径下使用CGI(或FastCGI)运行它 - 即/cgi500/,/cgi528/,... - Grey Panther
如果您使用的是Debian并且想要使用打包,我建议使用debootstrap创建一个chroot系统来保存您的PHP版本,然后在chroot系统内配置Apache。 - Max Tsepkov

10

对于我来说,使用多个apache + php实例从未真正引起我的兴趣,但这可能是最简单的方法。如果你不想过分追求简洁(KISS)... 这里有一个想法。

使你的apache运行,并尝试将其配置为类似于debian和ubuntu的方式,例如,为已加载模块创建目录。你的apache配置可以使用这样的行:

Include /etc/apache2/mods-enabled/*.load
Include /etc/apache2/mods-enabled/*.conf

接着构建你的第一个php版本,并给它一个包含版本号的前缀,例如/usr/local/php/5.2.8、/usr/local/php/5.2.6 ...

配置加载应该长成这样:

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

切换版本的方法很简单,只需更改apache目录中用于包含文件的load和conf文件为另一个版本的文件。你可以通过一个简单的bash脚本自动化这个过程(删除实际文件,将备用版本文件复制到原位,并重新启动apache)。

这种设置的优点是一切都很一致,只要保持php.ini的选项和模块相同(无论如何,您都必须使用CGI)。它们都通过SAPI。您的应用程序不需要任何更改,也不需要使用相对URL。

我认为这应该可以工作,但我没有尝试过,也不太可能这样做,因为我的要求与您不同。如果您尝试了,请留下评论。


8
注意:以下方法仅适用于Windows操作系统。
另一种方法(如果每次只运行一个PHP版本是可以接受的)是定义多个Apache服务,每个服务将使用不同的PHP版本。
首先,在Apache配置文件中使用条件语句:
 <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>

现在使用httpd.exe从命令行(管理员权限)创建两个独立的服务:
httpd.exe -k install -n Apache224_php54 -D php54

httpd.exe -k install -n Apache224_php55 -D php55

现在你可以一次启动上述其中一个服务(在启动另一个服务之前应该关闭一个服务)。
如果您以前已将Apache安装为服务,则可以使用以下命令删除它(用您使用的服务名称替换它):
apache -k uninstall -n Apache224

需要注意的是,我个人使用一种名为“Seobiseu”的“通知区域图标程序”来根据需要启动和停止服务。我已将上述两项服务添加到其中。


这实际上是一个非常聪明的解决方案。如果您想要并行运行多个服务,可以将 Listen 80Listen 81 分别包含在每个 ifdefine 中。 - caiosm1005
好主意,但问题是关于LAMP服务器,而不是WAMP服务器。 - Vinicius Monteiro

4
理解到您可能正在谈论本地/桌面计算机,并且可能希望继续讨论本地/桌面计算机,我会向您提供一种替代方案,以防它可能对您或其他人有所帮助:在云中设置多个虚拟服务器实例,并将您的代码作为git存储库(或mercurial,我想,尽管我没有个人经验,但你真正需要的只是一些去中心化的东西)共享。这样做的好处是可以尽可能地接近生产环境的体验,如果您有设置服务器的经验,那么这并不复杂(或者昂贵,如果您只想启动一个服务器,执行必要的操作,然后再关闭它,那么您所需要的费用大约为几美分甚至50美分,如果您让它保持运行,则可达几美元)。我现在把所有项目开发都放在云上,并发现管理基础设施比使用本地/非虚拟化安装时更加简单,而且使这种并排场景变得相当简单。如果您还没有考虑过这个想法,我只是想把这个想法提出来。

3

我刚刚成功地将Ubuntu 10上的PHP5.3降级了。

为了做到这一点,我使用了以下脚本:

#! /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

对于不知道如何在命令行中运行脚本的人,这里有一个简短的教程:

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

以下6个步骤将在您的主目录中创建一个名为“bin”的文件夹中创建一个脚本。然后,您可以通过调用以下命令来运行此脚本:

~/bin/myscriptname.sh

嗨!

希望这能对你们中的一些人有所帮助!

供参考,这是我得到脚本的地方: Ubuntu 10上的PHP5.2.10

那里有几个人都确认这个方法可行,而且它对我来说非常有效。


好的脚本,尽管因为我使用的是Power PC,所以Karmic对我没用。我只是使用这个脚本来删除我的当前安装,然后手动构建了2.14版本。 - Jason

2
Rasmus Lerdorf是创建PHP的人,他正在维护一个活跃的Vagrant解决方案,似乎可以解决您的需求。它允许快速切换PHP版本,目前支持20多个不同版本。它默认带有一个nginx服务器,但可以轻松地切换到预配置的apache2设置。它还默认支持MySQL。
这样,您将能够访问所有版本的PHP,在两个主要的Web服务器上部署,使用由PHP背后的大佬维护的漂亮vagrant box。
更多信息,请参考Lerdorf先生在https://youtu.be/6XnysJAyThs?t=2864上发表的演讲。
包含Vagrant解决方案的GitHub存储库可在https://github.com/rlerdorf/php7dev中找到。

这可能是“最好”的答案-为每个版本使用不同的VM(但您可以在一个IP地址上运行多个版本吗?)。 但是,讽刺的是php的创建者必须这样做-php最大的缺陷必须是版本之间缺乏兼容性,这使得像Joomla这样的东西几乎无用。 - EML

0
为了测试,我只是在不同的IP地址上运行多个httpd实例,因此我在192.168.0.70上运行php7,在192.168.0.56上运行php5.6。在生产环境中,我有一个运行旧版oscommerce的站点,运行php5.3,我只需为该站点使用不同的conf文件即可。
httpd -f /etc/apache2/php70.conf
httpd -f /etc/apache2/php53.conf

这也是一种干净的方式,可以为不同的站点拥有不同的php.ini文件。如果您只有几个站点,这是一个很好的组织方式,当您升级某些东西时,您不必同时担心超过1个站点。


0

我有几个项目在我的电脑上运行。如果您已经安装了多个版本,这个bash脚本应该可以帮助您轻松切换。目前我有php5、php5.6和php7.0,我经常根据我正在工作的项目来回切换。以下是我的代码。

请随意复制。确保您理解代码的工作原理。这是为了webhostin。在我的本地电脑上,我的修改存储在/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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接