# PHP 篇
PHP 是處理 php 腳本的解釋器
構建時,需要指定 MariaDB 的 socket 路徑,所以在 MariaDB 后安裝。
## 擴展庫說明
PHP 擴展庫按加載時間可分為:`動態庫(共享擴展)` 和 `靜態庫`
### 動態庫
動態庫是在程序運行時鏈接的,動態庫在編譯時不會放到連接的目標程序中,即可執行文件無法單獨運行
動態庫擴展名一般為:
| 系統 | 擴展名 |
| ---- | ------- |
| win | `*.dll` |
| unix | `*.so` |
### 靜態庫
靜態庫是在程序編譯時鏈接的,靜態庫在編譯時會直接整合到目標程序中,編譯成功的可執行文件可獨立運行
動態庫擴展名一般為:
| 系統 | 擴展名 |
| ---- | ------- |
| win | `*.lib` |
| unix | `*.a` |
### 動態庫和靜態庫區別
靜態編譯:靜態庫將需要的依賴在構建是已經從系統“拷貝”到程序中,執行時就不需要調用系統的庫,這會讓程序變得更大
動態編譯:動態庫構建了 1 個連接文件(`*.so`) ,用于連接程序和系統對應庫的文件,執行時需要調用系統的庫以及該庫對應的依賴項
- 性能:靜態庫優于動態庫,服務器硬件配置較差的,應該傾向于靜態庫
- 體積:靜態庫體積大于動態庫
- 升級:靜態庫升級需要重新構建 PHP,動態庫升級只需要重新生成連接文件(`*.so`)即可
- 穩定:靜態庫更加穩定,對于動態庫來講,如果系統對應庫升級,與動態庫對應的構建版本不一致,可能會遇到兼容性問題
### 擴展庫構建類型選擇
- 使用頻繁的擴展庫,推薦使用靜態編譯
- 更新頻繁的擴展庫,建議使用動態編譯
- 非官方認可擴展庫,建議使用動態編譯
[官方認可擴展庫列表](https://www.php.net/manual/zh/extensions.membership.php) 里的擴展,如有必要均可用靜態庫的方式構建,安全性和穩定性都由官方驗證過
## 靜態編譯 PECL 擴展
本次對 3 個 PECL 擴展,進行靜態編譯
- [redis-5.3.4](https://pecl.php.net/package/redis)
- [swoole-4.8.0](https://pecl.php.net/package/swoole)
- [yaml-2.2.1](https://pecl.php.net/package/yaml)
### 移動 PECL 擴展
將 PECL 擴展移動到 php 的 ext 目錄下
```sh
$ cd /package/lnmp/ext_static/
$ mv redis-5.3.4 /package/lnmp/php-8.0.12/ext/redis
$ mv swoole-4.8.0 /package/lnmp/php-8.0.12/ext/swoole
$ mv yaml-2.2.1 /package/lnmp/php-8.0.12/ext/yaml
# imagick 有用到也建議靜態構建
$ mv imagick-3.5.1 /package/lnmp/php-8.0.12/ext/imagick
```
### 重新生成 configure
引入新的擴展后,需要強制 PHP 重新生成配置腳本 `configure`
- 生成配置腳本依賴 autoconf
```sh
$ apt install autoconf -y
```
- 強制生成 configure
```sh
$ cd /package/lnmp/php-8.0.12/
$ mv configure{,.original}
$ ./buildconf --force
```
## 構建 PHP
### 創建構建目錄
```sh
mkdir /package/lnmp/php-8.0.12/build_php
```
### pkg-config 相關
構建 php 時,自己編譯的依賴包需要手動加入到 pkg-config 中
使用 export 是臨時加入環境變量中,但會永久記錄在編譯后的可執行文件信息里
#### 原理
1. 檢測路徑是否已經加入到 PKG_CONFIG_PATH 環境變量中,避免多次加入,從而造成混淪
```sh
$ echo $PKG_CONFIG_PATH
```
2. 將路徑加入到 PKG_CONFIG_PATH 環境變量中
加入單條:
```sh
$ export PKG_CONFIG_PATH=/path/to/pkgconfig1:$PKG_CONFIG_PATH
```
加入 2 條:
```sh
$ export PKG_CONFIG_PATH=/path/to/pkgconfig1:/path/to/pkgconfig2:$PKG_CONFIG_PATH
```
3. 檢測是否加入成功
```sh
$ pkg-config --list-all
```
#### 指令
```sh
$ export PKG_CONFIG_PATH=/server/sqlite3/lib/pkgconfig:$PKG_CONFIG_PATH
```
### 安裝必要依賴
```sh
$ apt install libxml2-dev
$ apt install libpng-dev libwebp-dev libjpeg-dev libxpm-dev libfreetype-dev
$ apt install libonig-dev
$ apt install libcurl4-openssl-dev
$ apt install libssl-dev
$ apt install libyaml-dev
```
- libonig-dev
對應提示:No package 'oniguruma' found
### 安裝指令
redis、imagick、swoole、yaml 這里使用最簡單的指令
更多指令請使用 `./congfigure -h | grep redis` 查看
```sh
$ cd /package/lnmp/php-8.0.12/build_php/
$ ../configure --prefix=/server/php \
--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 \
--enable-swoole \
--with-yaml
```
如果 imagick 需要靜態編譯,則增加如下一條信息:
```sh
--with-imagick=/server/ImageMagick \
```
### 編譯并安裝
```sh
$ make
$ make test
$ maek install
```
至此, php 安裝完成
## 配置 php.ini
php.ini 是 php 的配置文件,具體信息請查看 [官方手冊](https://www.php.net/manual/zh/ini.php)
### 配置文件模板
php 編譯完成后,在源碼包根目錄下會生成兩個 php.ini 模版文件
- 開發環境推薦
php.ini-development
- 部署環境推薦
php.ini-production
### 配置文件路徑
下面兩個指令,可以快速獲取到配置文件存放路徑
- 使用 php-config 程序
```sh
$ /server/php/bin/php --ini
```
- 使用 php 程序
```sh
$ /server/php/bin/php-config --ini-path
```
推薦:使用 php 程序查詢,會更加簡潔
### 拷貝配置文件
當前環境為部署環境,所以拷貝 php.ini-production
```sh
$ cp -p -r /package/lnmp/php-8.0.12/php.ini-production /server/php/lib/php.ini
```
### 檢測配置文件
使用 php 程序,快速檢測配置文件使用加載成功
```sh
$ /server/php/bin/php --ini
```
### 開啟 OPcache
OPcache 只能編譯為共享擴展
- 開啟方式
在 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 配置文件分:主進程配置文件和工作池進程配置文件
#### 主進程
主進程(master)配置文件,是針對整個 php-fpm 通用配置
路徑: /server/php/etc/php-fpm.conf
數量: 有且僅有,1 個
需求: 主進程配置文件必須存在
默認: 默認未創建
模板: /server/php/etc/php-fpm.conf.default
#### 工作池進程
工作池進程(pool)配置文件,是針對單個工作進程的配置文件
路徑: `/server/php/etc/php-fpm.d/*.conf`
數量: 允許多個
需求: 至少需要 1 個工作吃進程配置文件
默認: 默認未創建
模板: /server/php/etc/php-fpm.d/www.conf.default
#### 配置文件案例
- 主配置文件案例:
[php-fpm.conf](./php/php-fpm.conf.md)
- 工作池進程配置文件案例:
[sites.conf](./php/sites.conf.md)
## 參數說明
這里僅簡單了解下,關于更多參數說明,請查看 php-tutorial
### 工作進程配置參數
- [default]
子進程名,通常與子進程配置文件命名相同
- listen
php-fpm 工作池進程對應的監聽地址,可選端口或者 socket 文件
```conf
listen = /server/run/php/default.sock
```
- user/group
子進程用戶/用戶組,默認為 nobody
```conf
user = phpfpm
group = phpfpm
```
- listen.owner/listen.group
子進程監聽用戶/監聽用戶組,默認為 nobody
監聽用戶建議設置為 nginx 用戶
```conf
listen.owner = nginx
listen.group = nginx
```
- listen.allowed_clients
監聽允許訪問的客戶端 ip,默認僅允許本地訪問
```conf
listen.allowed_clients = 127.0.0.1
```
- listen.mode
監聽權限,僅支持監聽對象是 unix 套接字
如果使用 tcp 的端口方式訪問,注釋掉即可
```conf
listen.mode = 0660
```
## Systemd 管理
php-fpm 自帶了一套比較完善的進程管理指令,編譯完成后還會在構建目錄下生成 Unit 文件
### 加入 Systemd
1. 創建 php-fpm 單元文件
```sh
$ vim /usr/lib/systemd/system/php-fpm.service
```
內容查看 [php-fpm.service](./service/php-fpm.service.md)
2. 加入開機啟動
```sh
$ systemctl enable php-fpm
```
3. 重新加載 Systemd 配置文件
```sh
$ systemctl daemon-reload
```
## php-fpm 注意事項
### 工作進程
1 個 unix-socket,對應 1 個 php-fpm 工作進程
### 配置文件
1 個 php-fpm 工作進程配置文件對應 1 個 unix-socket
多個配置文件,不允許指向同一個 unix-socket,會出現沖突
每個配置文件:
- 必須設置單獨的 socket 文件路徑,如:tp6.sock、default.sock
- 可以設置自己的用戶,如:www、nginx、phpfpm、nobody
## 動態(共享)擴展
有年限的服務器,內部網站復雜,如果新人剛剛過來,確實不宜重新構建,如果缺少擴展,最好以動態方式安裝
這里以安裝 imagick 為例
### 依賴庫
imagick 擴展需要 ImageMagick 庫支持,下面是構建指令
```sh
$ cd /package/lnmp/ImageMagick-7.1.0-13/
$ nohup ./configure --prefix=/server/ImageMagick/ &
$ nohup make -j2 &
$ make check
$ make install
```
> 提示:靜態編譯 Imagick 擴展到 PHP,同樣需要先安裝 ImageMagick 包
```sh
# 使用 nohup + 指令 + & 程序將在后臺執行
# 需要使用 ps 指令來查看是否執行完畢
$ ps -ef|grep -E "id號|PID" |grep -v grep
```
### 使用 phpize
推薦大家使用,phpize 編譯共享 PECL 擴展庫
> phpize 指令
- 獲取幫助
```sh
$ /server/php/bin/phpize --help
```
- 獲取版本
```sh
$ /server/php/bin/phpize --version
$ /server/php/bin/phpize -v
```
- 清除 phpize 產生的臨時文件
```sh
$ /server/php/bin/phpize --clean
```
### 編譯動態擴展
php 核心擴展、內置擴展、捆綁擴展、pecl 擴展,它們的安裝方式都大同小異
```sh
$ cd /package/lnmp/ext_dynamic/imagick-3.5.1/
$ /server/php/bin/phpize
$ ./configure --with-php-config=/server/php/bin/php-config \
--with-imagick=/server/ImageMagick
$ make
$ make test
$ make install
```
### 開啟 imagick
imagick 作為共享擴展需要在 php.ini 文件里啟用
- 開啟方式
在 php.ini 第 960 行左右,添加一行內容
```ini
extension=imagick
```
- 重新加載 php-fpm
```sh
$ service php-fpm reload
```
> 到此,共享擴展安裝完成
## Composer
警告:服務器下建議不要安裝 git composer npm 等開發輔助工具
如果由需要,在開發環境處理好,然后拷貝進服務器即可
Composer 是一個 PHP 依賴管理工具
### 安裝
官方安裝方式
```sh
$ cd /server/php/bin
$ ./php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
# 驗證需要去官方獲取最新數據
$ ./php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ ./php composer-setup.php
$ ./php -r "unlink('composer-setup.php');"
```
網速不佳,也可以直接用阿里云鏡像 [下載 composer](https://mirrors.aliyun.com/composer/composer.phar)
### 全量鏡像
全局配置阿里云 Composer 全量鏡像
```sh
$ /server/php/bin/php /server/php/bin/composer.phar config -g repo.packagist composer https://mirrors.aliyun.com/composer/
```
取消阿里云 Composer 全量鏡像配置
```sh
$ /server/php/bin/php /server/php/bin/composer.phar config -g --unset repos.packagist
```
### nginx 站點
- 1 個站點
不同目錄或文件類型,可以指向不同的 unix-socket
- 多個站點
允許指向同一個 unix-socket,這是推薦的用法
## 數據庫管理工具
將 /package/lnmp/default/ 目錄下的 adminer、phpMyAdmin、phpRedisAdmin 加入到默認站點
```sh
$ cd /package/lnmp/default/
$ mv adminer-xxx.php /server/default/adminer.php
$ mv phpMyAdmin-xxx.php /server/default/pma
$ mv phpRedisAdmin-xxx.php /server/default/pra
```
### adminer
adminer 支持 MariaDB、sqlite3
使用 pdo 鏈接
不需要做任何配置
### phpMyAdmin
phpMyAdmin 支持 MariaDB
使用 mysqli 鏈接
需要簡單配置下:
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為的隨機字符串,這樣更加安全';
$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
$ cd /server/default/pra
$ /server/php/bin/php /server/php/bin/composer.phar 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 安裝包腳本