# PHP 多版本篇
很多老項目,通常都需要指定 PHP 的低版本才能正常運行
不管時部署環境還是開發環境都有這方面的需求,所以本次增加了 php 多版本的安裝教程
## 測試版本
本次我們主要選擇 2 款 php 來測試:
- [php 8.0](https://www.php.net/distributions/php-8.0.13.tar.gz) : 較新版本
- [php 8.1](https://www.php.net/distributions/php-8.1.0.tar.gz) : 最新版本,生態還未跟上
> 提示:php7.x 到 php 8.x 在安裝上不會有太大的區別,5.6 體驗實在糟糕,理論上已經不適合部署在新版服務器上了
## 安裝前的準備
下面這些是安裝 php 前我們需要先完成的工作
### 安裝靜態編譯
將 PECL 擴展拷貝到 php 的 ext 目錄下
```sh
# 拷貝到 php 8.1 源碼的擴展目錄
$ cp -p -r redis-5.3.4 /package/lnmp/php-8.1.0/ext/redis
$ cp -p -r yaml-2.2.2 /package/lnmp/php-8.1.0/ext/yaml
$ cp -p -r imagick-3.6.0 /package/lnmp/php-8.1.0/ext/imagick
# 拷貝到 php 8.0 源碼的擴展目錄
$ cp -p -r redis-5.3.4 /package/lnmp/php-8.0.13/ext/redis
$ cp -p -r yaml-2.2.2 /package/lnmp/php-8.0.13/ext/yaml
$ cp -p -r imagick-3.6.0 /package/lnmp/php-8.0.13/ext/imagick
```
### 重新生成 configure
引入新的擴展后,需要強制 PHP 重新生成配置腳本 `configure`
- 安裝 autoconf
```sh
$ apt install autoconf -y
```
- 強制生成 configure
```sh
# php 8.1
$ cd /package/lnmp/php-8.1.0/
$ mv configure{,.original}
$ ./buildconf --force
```
```sh
# php 8.0
$ cd /package/lnmp/php-8.0.13/
$ mv configure{,.original}
$ ./buildconf --force
```
### 安裝 ImageMagick
ImageMagick 是 php_imagick 的依賴庫,通常更新版本能提高 php_imagick 的執行效率
為了更高效,本次采用編譯安裝 ImageMagick 的最新穩定版
```sh
$ cd /package/lnmp/ImageMagick-7.1.0-17/
$ ./configure --prefix=/server/ImageMagick/
$ nohup make -j2 &
$ make check
$ make install
```
## 安裝 php
在安裝是 php 8.1 和 8.0 基本一致,依賴也一樣
其它版本可能依賴需要處理下,當然這不會像 5.6 那樣讓你頭疼
### 添加 pkg-config
構建 php 時,自己編譯的依賴包需要手動加入到 pkg-config 中
使用 export 是臨時加入環境變量中,但會永久記錄在編譯后的可執行文件信息里
```sh
$ export PKG_CONFIG_PATH=/server/sqlite3/lib/pkgconfig:$PKG_CONFIG_PATH
```
- 檢測是否加入成功
```sh
$ pkg-config --list-all
```
### 安裝必要依賴:
```sh
$ apt install libxml2-dev -y
$ apt install libcurl4-openssl-dev libssl-dev -y
$ apt install zlib1g-dev -y
$ apt install libpng-dev libwebp-dev libjpeg-dev libxpm-dev libfreetype-dev -y
$ apt install libonig-dev -y
$ apt install libyaml-dev -y
```
### 進入 php 構建目錄
- php 8.1
```sh
$ mkdir /server/php/8.1
$ mkdir /package/lnmp/php-8.1.0/build_php/
$ cd /package/lnmp/php-8.1.0/build_php/
```
- php 8.0
```sh
$ mkdir /server/php/8.0
$ mkdir /package/lnmp/php-8.0.13/build_php/
$ cd /package/lnmp/php-8.0.13/build_php/
```
### 安裝指令
安裝指令基本相同,差別僅在于 `--prefix=` 賦值不一樣
- php8.1 : `--prefix=/server/php/8.1`
- php8.0 : `--prefix=/server/php/8.0`
```sh
$ ../configure --prefix=/server/php/8.1 \
--enable-fpm \
--with-fpm-user=phpfpm \
--with-fpm-group=phpfpm \
--disable-short-tags \
--with-openssl \
--with-pcre-jit \
--with-zlib \
--with-curl \
--enable-exif \
--enable-ftp \
--enable-gd \
--with-webp \
--with-jpeg \
--with-xpm \
--with-freetype \
--enable-mbstring \
--enable-mysqlnd \
--with-mysql-sock=/run/mysqld/mysqld.sock \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--enable-sockets \
--enable-redis \
--with-imagick=/server/ImageMagick \
--with-yaml
```
編譯并安裝
```sh
$ nohup make -j2 &
$ make test
$ make install
```
## 配置 php.ini
php.ini 是 php 的配置文件,具體信息請查看 [官方手冊](https://www.php.net/manual/zh/ini.php)
### 模板
php 編譯完成后,在源碼包根目錄下會生成兩個 php.ini 模版文件
1. 開發環境推薦: php.ini-development
2. 部署環境推薦: php.ini-production
### 路徑
下面兩個指令,可以快速獲取到配置文件存放路徑
- php 8.1
```sh
# 使用 php-config 程序
$ /server/php/8.1/bin/php --ini
# 使用 php 程序
$ /server/php/8.1/bin/php-config --ini-path
```
- php 8.0
```sh
# 使用 php-config 程序
$ /server/php/8.0/bin/php --ini
# 使用 php 程序
$ /server/php/8.0/bin/php-config --ini-path
```
### 拷貝推薦文件
```sh
# php 8.1
$ cp -p -r /package/lnmp/php-8.1.0/php.ini-development /server/php/8.1/lib/php.ini
# php 8.0
$ cp -p -r /package/lnmp/php-8.0.13/php.ini-development /server/php/8.0/lib/php.ini
```
### 開啟 OPcache 擴展
OPcache 只能編譯為共享擴展,php8.0 和 php8.1 配置上一致
- 開啟方式
在 php.ini 第 960 行,將 `;` 去掉
```ini
zend_extension=opcache
```
- 性能配置
在 php.ini 第 1761 行,加入以下內容,可獲得較好性能
```ini
[opcache]
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1
```
## 配置 php-fpm
nginx 本身只能處理靜態頁面,如果要處理 php 腳本,就必須借助類似 php-fpm 的服務
在配置方面 php-fpm 分為: `主進程配置` 、 `工作池進程配置`
### 配置文件說明
下面是 php-fpm 的主進程配置和工作池進程配置的詳細說明
#### 主進程配置文件
主進程(master)配置文件,是針對整個 php-fpm 通用配置:
- 路徑 : `php 根目錄/etc/php-fpm.conf`
- 數量 : 1 個
- 命名 : 固定
- 需求 : 必須
- 默認 : 默認未創建
- 模板 : `php 根目錄/etc/php-fpm.conf.default`
#### 工作池進程配置文件
工作池進程(pool)配置文件,是針對單個工作進程的配置文件:
- 路徑 : `php 根目錄/etc/php-fpm.d/*.conf`
- 數量 : 若干個
- 命名 : 自定義
- 需求 : 至少 1 個
- 默認 : 默認未創建
- 模板 : `php 根目錄/etc/php-fpm.d/www.conf.default`
### php-fpm 配置范例
php8.1 和 php8.0 的 php-fpm 配置基本一致,詳細參考范例如下:
> php 8.1 的 php-fpm 配置范例
- [php 8.1 主配置文件參考](./php/8.1/php-fpm.conf.md)
- [php 8.1 工作池進程配置文件參考](./php/8.1/sites.conf.md)
> php 8.0 的 php-fpm 配置范例
- [php 8.0 主配置文件參考](./php/8.0/php-fpm.conf.md)
- [php 8.0 工作池進程配置文件參考](./php/8.0/sites.conf.md)
## Systemd 管理
php-fpm 自帶了一套比較完善的進程管理指令,編譯完成后還會在構建目錄下生成 Unit 文件
在 php 多版本共存的環境,我們需要自己去為每個 php 版本配置 Unit 文件
- [php 8.1 Unit 文件參考](./service/phpfpm-8.1.service.md)
- [php 8.0 Unit 文件參考](./service/phpfpm-8.0.service.md)
### 創建單元文件
- php 8.1
```sh
$ vim /usr/lib/systemd/system/phpfpm-8.1.service
```
輸入 php 8.1 Unit 文件參考中的內容
- php 8.0
```sh
$ vim /usr/lib/systemd/system/phpfpm-8.0.service
```
輸入 php 8.0 Unit 文件參考中的內容
### 單元文件加入開機啟動
```sh
$ systemctl enable phpfpm-8.1
$ systemctl enable phpfpm-8.0
```
### 重新加載 Systemd 配置文件
```sh
$ systemctl daemon-reload
```
## 注意事項
下面是 php 一些注意事項
### pid 文件
每個 php 版本的 php-fpm 只有一個唯一的 pid,其對應的 pid 文件只在兩個文件里出現:
1. php-fpm 主進程配置文件
2. php-fpm 針對 Systemd 的 Unit 文件
> 建議: 這兩個文件的 pid 文件路徑設置成一樣的
### unix-socket 文件
unix-socket 是類 unix 系統中,用來通訊的通用接口,每個 unix-socket 文件都具有單獨處理業務的能力
- 每個 php-fpm 工作進程,對應著單獨的 unix-socket 文件
- 多個 php-fpm 工作進程,不允許指向同一個 unix-socket 文件
- unix-socket 文件路徑,由 php-fpm `工作池進程配置文件` 指定
> 注意:不同 php-fpm `工作池進程配置文件` 中指向的 unix-socket 文件,不能出現重合的,否則程序會出錯
### php-fpm 用戶權限
php-fpm 用戶分為: `工作進程用戶和用戶組` 和 `工作進程監聽用戶和用戶組` 兩種
這兩類用戶均由 `工作池進程配置文件` 指定,而不是 `主進程配置文件` 指定
這意味著,php-fpm 中不同的 `工作池進程` 可以擁有不同的用戶權限,這種機制極大的提高了站點的安全性
#### 工作進程用戶
工作進程用戶和用戶組,指的是當前工作進程的用戶
#### 工作進程監聽用戶
工作進程監聽用戶和用戶組,對應著當前工作進程監聽的程序的用戶
## Composer
Composer 是一個 PHP 依賴管理工具
> 提示:使用 Composer 是,不要使用 root 用戶登錄,比如:用 www 用戶登錄就很不錯
### 安裝
通常我們只需要在主 PHP 版本上安裝一個 composer 即可
如果你要為不同版本的 php 安裝多個也可以,這里不做具體說明
這里采用阿里云鏡像 [直接下載 composer](https://mirrors.aliyun.com/composer/composer.phar)
需要單獨安裝的,可以去[composer 官方查看安裝說明](https://getcomposer.org/download/)
```sh
$ cd /server/php/8.1/bin
$ curl -O https://mirrors.aliyun.com/composer/composer.phar
# curl -o https://mirrors.aliyun.com/composer/composer.phar composer.phar
# wget https://mirrors.aliyun.com/composer/composer.phar
$ chmod +x composer.phar
$ ln -s composer.phar composer
```
### 升級
升級 composer 也非常簡單,建議使用國內全量鏡像后再升級
```sh
$ su www
$ /server/php/8.1/bin/php /server/php/8.1/bin/composer -V
$ /server/php/8.1/bin/php /server/php/8.1/bin/composer self-update
```
### 全量鏡像
國內首推阿里云 Composer 全量鏡像
```sh
$ su www
# 使用阿里云 Composer 全量鏡像
$ /server/php/8.1/bin/php /server/php/8.1/bin/composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
# 取消使用阿里云 Composer 全量鏡像
$ /server/php/8.1/bin/php /server/php/8.1/bin/composer config -g --unset repos.packagist
```
## 加入環境變量中
開發環境可以將 php 主版本的可執行文件加入到用戶環境變量中,這樣在操作上會便捷很多
由于 composer 不建議在 root 中使用,所以我們只在 www 用戶下添加:
- 加入到 bash 環境變量中:
```conf
# ~/.bashrc 文件底部增加
export PATH=$PATH:/server/php/8.1/bin:PATH=$PATH:/server/php/8.1/sbin
```
- 加入到 zsh 環境變量中:
```conf
# ~/.zshrc 文件底部增加
export PATH=$PATH:/server/php/8.1/bin:PATH=$PATH:/server/php/8.1/sbin
```
## PHP 版數據庫管理工具
將 adminer、phpMyAdmin、phpRedisAdmin 加入到默認站點
```sh
$ mv adminer-xxx.php /server/default/adminer.php
$ mv phpMyAdmin-xxx.php /server/default/pma
$ mv phpRedisAdmin-xxx.php /server/default/pra
```
### adminer
adminer 使用 pdo 鏈接數據庫,支持管理多種數據庫,不需要額外配置
adminer 無需配置
- 將服務器上 sql 文件導入到數據庫
```text
- sql文件路徑:文件必須和 adminer.php 在同級目錄下
- sql文件名稱:`adminer.sql` 或者 `adminer.sql.gz`
```
### phpMyAdmin
phpMyAdmin 使用 mysqli 鏈接,支持管理 MariaDB、MySQL
phpMyAdmin 需要配置:
1. 新建配置文件
在 pma 根目錄下新建 config.inc.php 文件
```sh
$ cd /server/default/pma/
$ touch config.inc.php
```
2. 配置文件內容
```php
<?php
declare(strict_types=1);
$cfg['blowfish_secret'] = '默認pma的密文,建議設置大于32為的隨機字符串,這樣更加安全';
switch (PHP_VERSION) {
case '8.0.13':
$cfg['blowfish_secret'] = 'php8.0.13下pma的密文';
break;
case '8.1.13':
$cfg['blowfish_secret'] = 'php8.1.0下pma的密文';
break;
}
$i = 0;
$i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
$cfg['UploadDir'] = '';
$cfg['SaveDir'] = '';
$cfg['TempDir'] = '/tmp/';
$cfg['DefaultLang'] = 'zh_CN';
$cfg['ThemeDefault'] = 'original';
```
其中,pma 的密文 `$cfg['blowfish_secret']` 參數需要重新設置
3. pma 密文
$cfg['blowfish_secret'] 參數用于設置 pma 密文,支持如下字符類型組合:
- 數值: `0-9`
- 大寫字母: `A-Z`
- 小寫字母: `a-z`
- ascii 特殊字符: `\~!@#$%^&*()_+-=[]{}\|;:'"/?.>,<`
### phpRedisAdmin
phpRedisAdmin 需要使用 composer 安裝依賴后,才能正常使用
```sh
$ use www
$ cd /server/default/pra
$ composer update
```
- Nginx 篇
- php 多版本
- 主配置文件
- 靜態站點配置模版
- tp6 站點的模版
- php 單版本
- 主配置文件
- 靜態站點配置模版
- tp6 站點的模版
- 靜態文件啟用壓縮
- 限制請求-http 塊
- 限制請求-server 塊
- 緩存配置文件
- tp6 站點的 fastcgi 模版
- MariaDB 篇
- MariaDB 主配置文件
- MariaDB 服務端子配置文件
- MariaDB 密鑰
- redis 篇
- sqlite3 篇
- php
- PHP 單版本篇
- PHP 多版本篇(new)
- php-fpm 主配置文件(php 單版本)
- php-fpm 工作池配置文件(php 單版本)
- '8.0(php 多版本)'
- php-fpm 主配置文件
- php-fpm 工作池進程配置文件
- '8.1(php 多版本)'
- php-fpm 主配置文件
- php-fpm 工作池進程配置文件
- service
- Nginx 系統單元文件
- MariaDB 系統單元文件
- redis 系統單元文件
- php-fpm 系統單元文件(php 單版本)
- phpfpm-8.0 系統單元文件(php 多版本)
- phpfpm-8.1 系統單元文件(php 多版本)
- vsftpd 篇
- pam-mysql 配置文件
- vsftpd 配置文件
- sh
- 刪除 lnmp 目錄腳本
- 創建 lnmp 目錄腳本
- 解壓 lnmp 安裝包腳本