---
title: Ubuntu 16.04 编译安装 PHP 7.2
date: 2017-12-14T19:42:00+08:00
tags:
  - Web
  - 技术

---

上一篇文章 [Linux 下 Nginx + PHP 环境的配置](https://blog.izgq.net/archives/895/) 扯了那么多复杂的概念，现在让我来说一说怎么把它用在实践之中。

最近我也想重新把 VPS 重装一遍，恰逢 PHP 发布了最新的 `PHP 7.2.0` 版本 (2017年12月14日)，所以就直接安装最新版本的 `PHP` 吧。

## 准备程序源码

直接到 `PHP` 官网： [php.net](http://php.net/downloads.php) 找到最新版的下载链接

在服务器找一个文件夹，用 `wget` 下载 `PHP` 的源码包：

```
wget http://am1.php.net/get/php-7.2.0.tar.gz/from/this/mirror -O php-7.2.0.tar.gz
```

解压备用：

```
tar -zxvf php-7.2.0.tar.gz
```

## 编译前的配置

一般来说，这种需要源码编译安装的软件，安装之前需要准备好编译环境以及程序需要依赖的库，以下是最最关键的实战经验。

首先我们准备编译环境，在 `Ubuntu 16.04 LTS` 中，默认并没有自带 C 和 C++ 的构建环境，我们安装一个叫 `build-essential` 的包即可，另外，`PHP` 还需要 `bison` `re2c` 和 `pkg-config` 才能安装，我们可以直接通过 `apt` 安装它们：

```
sudo apt install build-essential bison re2c pkg-config -y
```

接下来需要准备 `PHP-7.2.0` 的依赖包，大部分我们都可以通过 `apt` 来安装，唯一有一点要注意的是，`Ubuntu 16.04 LTS` 镜像源的 `libzip` 版本太老了，我们需要手动下一个新版本，才能让 `PHP` 的 `zip` 扩展支持加密的 `zip` 文件的操作。

安装依赖的命令：

```
sudo apt install build-essential bison re2c pkg-config libxml2-dev libbz2-dev libssl-dev libcurl4-openssl-dev libjpeg-dev libpng12-dev libfreetype6-dev libgmp-dev libreadline6-dev libxslt1-dev libzip-dev
```

如果没有用 `PHP` 来处理加密 `zip` 的需求的话，也可以直接用 `apt` 默认的 `libzip` 包，刚刚的命令已经带上了，想完美支持的话，我们需要到 `libzip` 的官网下一个，编译的时候另外指定：

```
wget https://libzip.org/download/libzip-1.3.2.tar.gz
tar -zxvf libzip-1.3.2.tar.gz
```

这时候的目录结构是这样的，假设我刚刚是在 ~ 目录进行刚刚所描述的操作：

```
~/libzip-1.3.2/
~/php-7.2.0/
```

接下来就是最重要的运行 `./configure` 生成 `makefile` 了，不多说，直接上我调整好的套路。如果没有下载源码的话，请将 `--with-libzip=../libzip-1.3.2 \` 替换成 `--with-libzip \` （注意 `\` 之前一定有一个空格！）

```
./configure \
--prefix=/usr/local/php \
--with-config-file-path=/etc \
--enable-fpm \
--enable-inline-optimization \
--disable-debug \
--disable-rpath \
--enable-shared  \
--with-libxml-dir \
--with-xmlrpc \
--with-mhash \
--with-pcre-regex \
--with-sqlite3 \
--with-zlib \
--with-libzip=../libzip-1.3.2 \
--enable-bcmath \
--with-iconv \
--with-bz2 \
--with-openssl \
--enable-calendar \
--with-curl \
--with-cdb \
--enable-dom \
--enable-exif \
--enable-fileinfo \
--enable-filter \
--with-pcre-dir \
--enable-ftp \
--with-gd \
--with-openssl-dir \
--with-jpeg-dir \
--with-png-dir \
--with-zlib-dir \
--with-freetype-dir \
--enable-gd-jis-conv \
--with-gettext \
--with-gmp \
--with-mhash \
--enable-json \
--enable-mbstring \
--enable-mbregex \
--enable-mbregex-backtrack \
--with-libmbfl \
--with-onig \
--enable-pdo \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-pdo-sqlite \
--with-readline \
--enable-session \
--enable-shmop \
--enable-simplexml \
--enable-sockets  \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-wddx \
--with-libxml-dir \
--with-xsl \
--enable-zip \
--enable-mysqlnd-compression-support \
--with-pear \
--enable-opcache
```

看到以下信息，这时候说明可以编译了，若出现了其它报错则需要一一排查：

```

Generating files
configure: creating ./config.status
creating main/internal_functions.c
creating main/internal_functions_cli.c
+--------------------------------------------------------------------+
| License:                                                           |
| This software is subject to the PHP License, available in this     |
| distribution in the file LICENSE.  By continuing this installation |
| process, you are bound by the terms of this license agreement.     |
| If you do not agree with the terms of this license, you must abort |
| the installation process at this point.                            |
+--------------------------------------------------------------------+

Thank you for using PHP.

config.status: creating php7.spec
config.status: creating main/build-defs.h
config.status: creating scripts/phpize
config.status: creating scripts/man1/phpize.1
config.status: creating scripts/php-config
config.status: creating scripts/man1/php-config.1
config.status: creating sapi/cli/php.1
config.status: creating sapi/fpm/php-fpm.conf
config.status: creating sapi/fpm/www.conf
config.status: creating sapi/fpm/init.d.php-fpm
config.status: creating sapi/fpm/php-fpm.service
config.status: creating sapi/fpm/php-fpm.8
config.status: creating sapi/fpm/status.html
config.status: creating sapi/cgi/php-cgi.1
config.status: creating ext/phar/phar.1
config.status: creating ext/phar/phar.phar.1
config.status: creating main/php_config.h
config.status: executing default commands
```

## 开始编译安装 PHP 7.2.0

首先进入 `PHP` 源码目录，然后一行命令，简单粗暴：

```
cd php-7.2.0/
make && sudo make install
```

成功后可以看到如下的信息：

```
Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20170718/
Installing PHP CLI binary:        /usr/local/php/bin/
Installing PHP CLI man page:      /usr/local/php/php/man/man1/
Installing PHP FPM binary:        /usr/local/php/sbin/
Installing PHP FPM defconfig:     /usr/local/php/etc/
Installing PHP FPM man page:      /usr/local/php/php/man/man8/
Installing PHP FPM status page:   /usr/local/php/php/php/fpm/
Installing phpdbg binary:         /usr/local/php/bin/
Installing phpdbg man page:       /usr/local/php/php/man/man1/
Installing PHP CGI binary:        /usr/local/php/bin/
Installing PHP CGI man page:      /usr/local/php/php/man/man1/
Installing build environment:     /usr/local/php/lib/php/build/
Installing header files:          /usr/local/php/include/php/
Installing helper programs:       /usr/local/php/bin/
  program: phpize
  program: php-config
Installing man pages:             /usr/local/php/php/man/man1/
  page: phpize.1
  page: php-config.1
Installing PEAR environment:      /usr/local/php/lib/php/
[PEAR] Archive_Tar    - installed: 1.4.3
[PEAR] Console_Getopt - installed: 1.4.1
[PEAR] Structures_Graph- installed: 1.1.1
[PEAR] XML_Util       - installed: 1.4.2
[PEAR] PEAR           - installed: 1.10.5
Wrote PEAR system config file at: /usr/local/php/etc/pear.conf
You may want to add: /usr/local/php/lib/php to your php.ini include_path
/root/php-7.2.0/build/shtool install -c ext/phar/phar.phar /usr/local/php/bin
ln -s -f phar.phar /usr/local/php/bin/phar
Installing PDO headers:           /usr/local/php/include/php/ext/pdo/
```

到了这一步，`PHP` 已经安装在你的服务器上了。

## 配置 PHP

### 配置环境变量

要在命令行里面直接通过 `php` 之类的命令直接运行 `php` ，我们需要将 `bin` 目录加入到系统的环境变量中，方法是：

```bash
vim /etc/profile
```

在文件最末尾加上：

```bash
PATH=$PATH:/usr/local/php/bin
export PATH
```

保存以后，执行 `source /etc/profile` 使环境变量生效。

测试一下：

```bash
php -v
```

配置无误的话我们可以得到这样的输出

```
PHP 7.2.0 (cli) (built: Dec  4 2017 17:09:34) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2017 Zend Technologies
```

### 配置 PHP-FPM

增加 `php-fpm` 命令：

```bash
cp sapi/fpm/init.d.php-fpm /usr/local/bin/php-fpm
chmod +x /usr/local/bin/php-fpm
```

### 初始化 PHP 和 PHP-FPM 的配置

首先先把默认的配置拷贝一下：

```bash
cp php.ini-production /etc/php.ini
cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
```

### 设置 PHP-FPM 执行的用户和用户组

网站的权限管控也是一个很关键的事情，虽然说问题发生的几率微乎其微，但是我们很难保证我们的程序一定不会翻车被人 getshell。所以，我们要确保 `PHP-FPM` 只能操作自己网站的文件，而不能访问其它地方，这样可以最大化地减小网站万一被黑带来的危害。

这里一个安全性比较好的策略是，所有关于网站的程序都运行在 `website` 组中，用 `nginx` 用户运行 `nginx`，在 `PHP-FPM` 中配置不同用户来运行不同的网站，建议在生产环境中这么配置。

| 程序 | group | user |
|:---:|:---:|:---:|
| Nginx 服务器 | website | nginx |
| Typecho 博客 | website | site-1 |
| 另一个PHP网站 | website | site-2 |
| ... | website | site-n |

当然，如果你比较懒的话，也可以只配置一个 site 的用户和配置，然后各个网站共用一个 pool 也是可以的，这取决于你对安全性的追求。

首先我们得有这个 `website` 用户组，这里用 `groupadd website` 来创建。

然后再把相应的用户创建出来，并且禁用这个用户登录的 `shell`：

```bash
useradd -s /sbin/nologin -g website site-1
```

再把你传到服务器上的网站目录的所有者和组改成 `website:site-1` ，假设网站位于 `/var/www/site-1`，那就运行：

```bash
chown -R website:site-1 /var/www/site-1
```

然后再把文件权限改成 `0755` ，它是一个八进制数，也就是 `rwxr-xr-x` ，只有自己才能写入，其它用户只有读取和执行的权限：

```bash
chmod -R 0755 /var/www/site-1
```

我们需要新建一个 `php-fpm` 的 `pool`（也叫进程池） 配置，每次增加新的网站，我们都可以从默认的配置拷贝一份新的出来使用，如，我们这里拷贝一份 `site-1.conf` 。

```bash
cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/site-1.conf
```

然后打开文本编辑器编辑：

```bash
vim /usr/local/php/etc/php-fpm.d/site1.conf
```

忽略那些 `;` 开头的注释，实际上我们需要改的只有这几行

```
; Start a new pool named 'www'.
; the variable $pool can be used in any directive and will be replaced by the
; pool name ('www' here)
[www]

user = nobody
group = nobody

listen = 127.0.0.1:9000
```

我们把 `pool name` 改一个名字，不同站点的名字不能一样，例如，我们可以把它改成 `site-1` ，然后再修改一下 `listen` 的端口，保证不同的 `pool` 监听的连接不冲突，这是一个示例：

```
[site-1]

user = site-1
group = website

listen = 127.0.0.1:9000
```

保存以后，运行 `php-fpm start` 就能启动网站服务了，当配置有变动时，我们调用 `php-fpm reload` 即可让新配置生效。

### 设置开机自动启动 PHP-FPM

Ubuntu 16.04 LTS 是通过 `systemd` 管理服务的，所以服务可以按照如下方法设置：

```bash
vim /etc/systemd/system/php-fpm.service
```

内容我们这么写：

```
[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target
[Service]
Type=forking
ExecStart=/usr/local/bin/php-fpm start
ExecReload=/usr/local/bin/php-fpm reload
ExecStop=/usr/local/bin/php-fpm stop
[Install]
WantedBy=multi-user.target
```

保存以后，设置开机自启：

```bash
systemctl enable php-fpm.service
```

## 安装配置 Nginx

安装 `Nginx` 有很多方法，一般用 `sudo apt install nginx` 装的 `Nginx` 就能满足要求。

首先修改 `nginx.conf` ，把 `nginx` 的运行用户和用户组改成

```
user nginx website;
```

然后修改 `server` 配置，假设原来的网站配置是下面的情况：

```
server {
    listen 80;
    server_name izgq.net;
    root /var/www/site-1;
}
```

首先配置 `index` ，加入默认 `index.php` ：

```
index index.html index.php;
```

然后，在上篇文章 [Linux 下 Nginx + PHP 环境的配置](https://blog.izgq.net/archives/895/) 选一个适合的配置，粘贴即可。

一个例子：

```
server {
    listen 80;
    server_name izgq.net;
    root /var/www/site-1;
    index index.html index.php;

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass 127.0.0.1:9000;
        include fastcgi.conf;
    }
}
```

保存好后，别忘记让 nginx 重新加载一下配置：

```bash
sudo service nginx reload
```

执行完这个操作，你的网站就已经部署好啦～

参考文章：

[CentOS7重装之路-PHP7安装使用篇 · 麦麦小家](https://blog.micblo.com/2017/01/24/CentOS7%E9%87%8D%E8%A3%85%E4%B9%8B%E8%B7%AF-PHP7%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8%E7%AF%87/)
