Aldebaran

人生最棒的感觉,就是你做到别人说你做不到的事。

0%

PHP7.2源码编译

三田寺円

前言

php7是PHP5.6之后的一次大版本升级,速度以及性能比php5系列的任何一版本都要快。

鉴于之前的脚本和文档都是关于PHP5.6,因此在CentOS6和CentOS7上测试编译,并且通过测试。(Ubuntu同理)

本文仅仅记录实验过程。本文仅供参考,请根据需求修改。

安装环境依赖包

如果是centos系统下执行

$ yum -y install gcc gcc+ gcc-c++ gcc-g77 flex bison autoconf snmp automake \
    bzip2-devel zlib-devel readline-devel ncurses-devel libjpeg-devel \
    libpng-devel libtiff-devel freetype-devel pam-devel openssl-devel \
    mod_ssl libxml2-devel gettext-devel pcre-devel curl-devel mysql-devel \
    libevent-devel libtool-ltdl gmp-devel openldap openldap-devel \
    ImageMagick-devel libtool net-snmp-devel libwebp libwebp-devel

如果是ubuntu系统下执行

$ sudo apt-get update
$ sudo apt -y install build-essential bison re2c pkg-config libxml2-dev \
    openssl libssl-dev libjpeg-dev libpng-dev libtool-bin

下载/解压

  • 下载 libiconv, libmcrypt, mcrypt, mhash, php

    $ cd /usr/local/src
    $ wget https://ftp.gnu.org/gnu/libiconv/libiconv-1.15.tar.gz
    $ wget https://sourceforge.net/projects/mcrypt/files/Libmcrypt/2.5.8/libmcrypt-2.5.8.tar.gz
    $ wget https://sourceforge.net/projects/mcrypt/files/MCrypt/2.6.8/mcrypt-2.6.8.tar.gz
    $ wget https://sourceforge.net/projects/mhash/files/mhash/0.9.9.9/mhash-0.9.9.9.tar.gz
    $ wget http://cn2.php.net/distributions/php-7.2.5.tar.gz
  • 解压压缩包

    $ cd /usr/local/src
    $ tar zxf libiconv-1.15.tar.gz
    $ tar zxf libmcrypt-2.5.8.tar.gz
    $ tar zxf mcrypt-2.6.8.tar.gz
    $ tar zxf mhash-0.9.9.9.tar.gz
    $ tar zxf php-7.2.5.tar.gz

安装编译依赖包

如使用其他系统环境的,请注意在某些依赖安装环节的差异

  • 加载lib

    $ touch /etc/ld.so.conf.d/lib-lib64.all.conf
    $ echo "/usr/lib" >> /etc/ld.so.conf.d/lib-lib64.all.conf
    $ echo "/usr/lib64" >> /etc/ld.so.conf.d/lib-lib64.all.conf
    $ echo "/usr/local/lib" >> /etc/ld.so.conf.d/lib-lib64.all.conf
    $ echo "/usr/local/lib64" >> /etc/ld.so.conf.d/lib-lib64.all.conf
    $ /sbin/ldconfig
  • 安装libiconv

    ## libiconv库为需要做转换的应用程序提供了一个iconv命令,以实现一个字符编码到另一个字符编码的转换,比如它可以将UTF8编码转换成GB18030编码,反过来也行
    
    $ cd /usr/local/src/libiconv-1.15
    $ ./configure --prefix=/usr/local
    $ make && make install
    $ /sbin/ldconfig
  • 安装libmcrypt(php7.1后不支持mcrypt系列函数)

    $ cd /usr/local/src/libmcrypt-2.5.8
    $ ./configure && make && make install
    $ /sbin/ldconfig
    $ cd libltdl/
    $ ./configure --prefix=/usr/local --enable-ltdl-install
    $ make && make install
    $ /sbin/ldconfig
  • 安装mcrypt(php7.1后不支持mcrypt系列函数)(可选)

    $ cd /usr/local/src/mcrypt-2.6.8
    $ ./configure
    $ make && make install
  • 安装mhash

    $ cd /usr/local/src/mhash-0.9.9.9
    $ ./configure
    $ make && make install
    $ /sbin/ldconfig

安装php

php编译参数

PHP5.6和PHP7的参数是不一样的(这里不推荐PHP5.6 备份一下PHP5.6的编译参数)

下面的编译参数请根据需求修改。

  • PHP 5.6(不推荐,能不用PHP5就尽量不用了)

    $ ./configure --prefix=/usr/local/php-5.6.x \
    --with-config-file-path=/usr/local/php-5.6.x/etc \
    --with-pear=/usr/local/php-5.6.x/php \
    --enable-fpm \
    --enable-pcntl \
    --with-mysql \
    --with-mysqli \
    --with-pdo_mysql \
    --with-iconv-dir=/usr/local \
    --with-zlib \
    --with-bz2 \
    --with-curl \
    --with-libxml-dir \
    --with-gd \
    --with-jpeg-dir \
    --with-png-dir \
    --with-zlib-dir \
    --with-freetype-dir \
    --with-openssl \
    --with-gettext \
    --with-snmp \
    --with-mhash \
    --with-mcrypt \
    --enable-gd-native-ttf \
    --enable-gd-jis-conv \
    --enable-mbstring \
    --enable-shmop \
    --enable-sockets \
    --enable-zip \
    --enable-ftp \
    --enable-bcmath \
    --enable-soap \
    --enable-calendar \
    --enable-dba \
    --disable-ipv6 \
    --enable-opcache
    
    $ /usr/bin/make ZEND_EXTRA_LIBS='-liconv' && /usr/bin/make install
    $ ln -s /usr/local/php-5.6.x /usr/local/php
  • PHP 7.2

    $ cd /usr/local/src/php-7.2.5
    $ ./configure --prefix=/usr/local/php-7.2.5 \
    --with-config-file-path=/usr/local/php-7.2.5/etc \
    --enable-fpm \
    --enable-pcntl \
    --with-pear=/usr/local/php-7.2.5/share/php \
    --with-pdo-mysql \
    --with-mysqli \
    --with-iconv-dir=/usr/local \
    --with-zlib \
    --with-bz2 \
    --with-curl \
    --with-libxml-dir \
    --with-gd \
    --with-jpeg-dir \
    --with-png-dir \
    --with-zlib-dir \
    --with-freetype-dir \
    --with-openssl \
    --with-gettext \
    --with-snmp \
    --with-mhash \
    --enable-mbstring \
    --enable-gd-jis-conv \
    --enable-shmop \
    --enable-sockets \
    --enable-zip \
    --enable-ftp \
    --enable-bcmath \
    --enable-soap \
    --enable-calendar \
    --enable-dba \
    --disable-ipv6 \
    --enable-opcache
    
    $ /usr/bin/make ZEND_EXTRA_LIBS='-liconv' && /usr/bin/make install
    $ ln -s /usr/local/php-7.2.5 /usr/local/php

安装ImageMagick/libevent

ImageMagick(可选)

如果需要imagick模块那么服务器上也需要安装ImageMagick

  • 安装ImageMagick

    # 如果是ubuntu系统下执行
    $ apt install imagemagick
    
    # 如果是CentOS系统下执行
    $ yum install ImageMagick ImageMagick-devel

如果对ImageMagick版本有需求则需要编译了。(可选)

  • 编译ImageMagick

    $ wget http://transloadit.imagemagick.org/download/ImageMagick-7.0.7-30.tar.gz
    
    $ ## 编译依赖库ImageMagick,centos自带的ImageMagick版本较低
    $ cd /usr/local/src
    $ tar -zxf ImageMagick-7.0.7-30.tar.gz
    $ cd ImageMagick-7.0.7-30
    $ ./configure
    $ make && make install
    $ /sbin/ldconfig

编译libevent

  • libevent

    ## 下载libevent
    $ wget https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz
    
    ## 编译拓展libevent
    $ cd /usr/local/src
    $ tar xzf libevent-2.1.8-stable.tar.gz
    $ cd libevent-2.1.8-stable
    $ ./configure --prefix=/usr/local
    $ make && make install
    $ /sbin/ldconfig

安装php扩展

什么是PHP扩展?

为PHP提供一些扩展的功能

安装php扩展的方式有两种:手动编译和pecl安装。

1. 手动安装

需要追求最新的功能或者需要特定的版本要手动编译安装

下面列出常用的模块报编译方式

  • imagick

    ## 下载imagick
    $ cd /usr/local/src
    $ wget http://pecl.php.net/get/imagick-3.4.3.tgz
    
    ## 编译拓展imagick
    $ tar zxf imagick-3.4.3.tgz
    $ cd imagick-3.4.3
    $ /usr/local/php/bin/phpize
    $ ./configure --with-php-config=/usr/local/php/bin/php-config
    $ make && make install
  • memcache(不支持PHP7.2)

    ## PHP7.2不支持 memcache
    ## memcache 比 memcached 早出现,所以一些老的代码可能还在用 memcache 扩展。memcached 后来出现,并且大部分框架都支持 memcached。
    
    ## 下载memcache
    $ wget http://pecl.php.net/get/memcache-3.0.8.tgz
    
    ## 编译拓展memcache
    $ cd /usr/local/src
    $ tar zxf memcache-3.0.8.tgz
    $ cd memcache-3.0.8
    $ /usr/local/php/bin/phpize
    $ ./configure --with-php-config=/usr/local/php/bin/php-config --with-zlib-dir --enable-memcache
    $ make && make install
  • phpredis

    ## 下载phpredis
    $ wget https://pecl.php.net/get/redis-3.1.4.tgz
    
    ## 编译拓展redis
    $ cd /usr/local/src
    $ tar zxf redis-3.1.4.tgz
    $ cd redis-3.1.4
    $ /usr/local/php/bin/phpize
    $ ./configure --with-php-config=/usr/local/php/bin/php-config --enable-redis
    $ make && make install
  • mongo

    ## 下载mongo
    $ wget https://pecl.php.net/get/mongo-1.6.16.tgz
    
    ## 编译拓展mongo
    $ cd /usr/local/src
    $ tar xzf mongo-1.6.16.tgz
    $ cd mongo-1.6.16
    $ /usr/local/php/bin/phpize
    $ ./configure --with-php-config=/usr/local/php/bin/php-config
    $ make && make install
  • xdebug(跟踪、调试和分析PHP程序的运行状况)

    ## 下载xdebug
    $ wget https://xdebug.org/files/xdebug-2.5.5.tgz
    
    ## 编译拓展xdebug
    ## 如果需要将 Xdebug 扩展和 OPcache 一起使用,必须在 Xdebug 扩展之前加载 OPcache 扩展。
    $ cd /usr/local/src
    $ tar xzf xdebug-2.5.5.tgz
    $ cd xdebug-2.5.5
    $ /usr/local/php/bin/phpize
    $ ./configure --with-php-config=/usr/local/php/bin/php-config
    # make && make install
    $ make -j `grep processor /proc/cpuinfo | wc -l` && make install

2. pecl安装

什么是PECL?

PECL 是PHP扩展的存储库,提供了所有已知扩展名和目录,用于下载和开发PHP扩展, 类似于Python的pip

下面来试试

$ /usr/local/php/bin/pecl install imagick

# memcache不支持 memcachePHP7.2,用 memcached 代替。
# memcache 比 memcached 早出现,所以一些老的代码可能还在用 memcache 扩展。memcached 后来出现,并且大部分框架都支持 memcached。
$ /usr/local/php/bin/pecl install memcached

$ /usr/local/php/bin/pecl install redis
$ /usr/local/php/bin/pecl install mongo

## 如果需要将 Xdebug 扩展和 OPcache 一起使用,必须在 Xdebug 扩展之前加载 OPcache 扩展。
$ /usr/local/php/bin/pecl install xdebug

配置php

修改PHP配置文件

配置 php-fpm.conf

$ cp /usr/local/php/etc/php-fpm.conf{,.default}
$ cat > /usr/local/php/etc/php-fpm.conf <<EOF
[global]
pid = /usr/local/php-7.2.5/var/run/php-fpm.pid
error_log = /usr/local/php-7.2.5/var/log/php-fpm.log
log_level = error
[www]
listen = /usr/local/php/etc/php-cgi.socket
user = nginx
group = nginx
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
pm = static
pm.max_children = 200
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 30
pm.max_requests = 5000
request_slowlog_timeout = 5s
slowlog = /usr/local/php-7.2.5/var/log/php-fpm.log.slow
rlimit_files = 51200
EOF

配置php.ini

$ cp /usr/local/src/php-7.2.5/php.ini-production /usr/local/php-7.2.5/etc/php.ini
$ cp /usr/local/php-7.2.5/etc/php.ini{,.default}
$ ext_path=`ls /usr/local/php-7.2.5/lib/php/extensions/`
$ cat >> /usr/local/php-7.2.5/etc/php.ini <<EOF
extension_dir = /usr/local/php/lib/php/extensions/${ext_path}
extension = "memcache.so"
extension = "imagick.so"
extension = "redis.so"
zend_extension = "opcache.so"
output_buffering = On
cgi.fix_pathinfo=0
EOF

# 修改文件上传大小
$ sed -i "s#^upload_max_filesize = 2M#upload_max_filesize = 5M#" /usr/local/php-7.2.5/etc/php.ini

# 限制php运行目录
$ sed -i "s#^;open_basedir =#open_basedir = /tmp:/data/wwwroot/:/data/ftp/:/www/web#" /usr/local/php-7.2.5/etc/php.ini

# 关闭php版本信息
$ sed -i "s#^expose_php = On#expose_php = Off#" /usr/local/php-7.2.5/etc/php.ini
$ sed -i "s#^allow_url_fopen = On#allow_url_fopen = Off#" /usr/local/php-7.2.5/etc/php.ini

# opcache
$ sed -i "s#^;opcache.enable=0#opcache.enable=1#" /usr/local/php-7.2.5/etc/php.ini
$ sed -i "s#^;opcache.enable_cli=0#opcache.enable_cli=1#" /usr/local/php-7.2.5/etc/php.ini
$ sed -i "s#^;opcache.memory_consumption=64#opcache.memory_consumption=128#" /usr/local/php-7.2.5/etc/php.ini
$ sed -i "s#^;opcache.interned_strings_buffer=4#opcache.interned_strings_buffer=8#" /usr/local/php-7.2.5/etc/php.ini
$ sed -i "s#^;opcache.max_accelerated_files=2000#opcache.max_accelerated_files=4000#" /usr/local/php-7.2.5/etc/php.ini
$ sed -i "s#^;opcache.revalidate_freq=2#opcache.revalidate_freq=60#" /usr/local/php-7.2.5/etc/php.ini
$ sed -i "s#^;opcache.fast_shutdown=0#opcache.fast_shutdown=1#" /usr/local/php-7.2.5/etc/php.ini

# 禁用安全函数
# disable_functions 本指令允许你基于安全原因禁止某些函数。接受逗号分隔的函数名列表作为参数。
# disable_functions 不受安全模式的影响。 本指令只能设置在 php.ini 中
$ sed -i "s#^disable_functions =#disable_functions = passthru,ini_restore,eval#" /usr/local/php-7.2.5/etc/php.ini

# 修改时区,具体时区参考:http://php.net/manual/zh/timezones.php
$ sed -i "s#^;date.timezone =#date.timezone = Asia/Shanghai#" /usr/local/php-7.2.5/etc/php.ini

启动服务

修改php-fpm启动脚本

$ vim /etc/init.d/php-fpm
#!/bin/bash

## BEGIN INIT INFO
# Provides:          php-fpm
# Required-Start:    $remote_fs $network
# Required-Stop:     $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts php-fpm
# Description:       starts the PHP FastCGI Process Manager daemon
## END INIT INFO

prefix=/usr/local/php
exec_prefix=${prefix}

php_fpm_BIN=${exec_prefix}/sbin/php-fpm
php_fpm_CONF=${prefix}/etc/php-fpm.conf
php_fpm_PID=${prefix}/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 --daemonize $php_opts && chown -R nginx.nginx ${prefix}/etc/php-cgi.socket

                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-quit"
                        exit 1
                else
                        echo " done"
                fi
        ;;

        status)
                if [ ! -r $php_fpm_PID ] ; then
                        echo "php-fpm is stopped"
                        exit 0
                fi

                PID=`cat $php_fpm_PID`
                if ps -p $PID | grep -q $PID; then
                        echo "php-fpm (pid $PID) is running..."
                else
                        echo "php-fpm dead but pid file exists"
                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|status}"
                exit 1
        ;;

esac

设置开机启动

$ chmod 755 /etc/init.d/php-fpm
$ chkconfig --level 35 php-fpm on