准备工作
这是 《Linux 下纯手工搭建 PHP 环境》 2026 年重构版本!
这几年我们不断迭代,文档存在遗留代码也存在错误的说明,本次重构主要涉及:
- 文档内容紧凑,提升阅读体验;
- 修复已知错误;
- 优化目录结构;
- 优化一键脚本;
- 升级一键构建包;
包列表
主要涉及发行版和软件包如下。
zsh
➜ ~ uname -a
Linux debian13 6.12.63+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.63-1 (2025-12-30) x86_64 GNU/Linux
root ➜ ~ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 13 (trixie)
Release: 13
Codename: trixiemd
1. sqlite-autoconf-3510200.tar.gz
2. redis-8.6.0.tar.gz
3. postgresql-18.1.tar.bz2
4. php-8.5.2.tar.xz
- apcu-5.1.28.tgz
- redis-6.3.0.tgz
- xdebug-3.5.0.tgz
5. nginx-1.28.2.tar.gz
- openssl-3.5.5.tar.gz
- pcre2-10.47.tar.bz2
- zlib-1.3.1.tar.xz
6. mysql-8.4.8.tar.gzmd
| package | url |
| ---------- | --------------------------------------------- |
| SQLite3 | https://www.sqlite.org/ |
| Redis.1 | https://github.com/redis/redis-hashes |
| Redis.2 | https://download.redis.io/redis-stable.tar.gz |
| PostgreSQL | https://www.postgresql.org/ |
| PHP | https://www.php.net/ |
| PHP extend | http://pecl.php.net/ |
| Nginx | http://nginx.org/ |
| zlib | http://www.zlib.net/ |
| openssl | https://openssl-library.org/ |
| pcre2 | https://github.com/PCRE2Project/pcre2 |
| MySQL | https://www.mysql.com/ |zsh
root ➜ ~ lt5 /server -l --no-time
Permissions Size User Name
drwxr-xr-x - root /server
drwxr-x--- - mysql ├── data
drwxr-xr-x - root ├── default
drwxr-xr-x - root ├── etc
drwxr-x--- - mysql │ ├── mysql
drwxr-x--- - nginx │ ├── nginx
drwxr-x--- - nginx │ │ └── custom
drwxr-x--- - php │ ├── php
drwxr-x--- - php │ │ ├── 85
drwxr-x--- - php │ │ │ ├── php-fpm.d
drwxr-x--- - php │ │ │ │ ├── default.conf
drwxr-x--- - php │ │ │ │ ├── ...
drwxr-x--- - php │ │ │ └── php-fpm.conf
drwxr-x--- - php │ │ └── tools
drwxr-x--- - postgres │ ├── postgres
drwx------ - postgres │ │ └── tls
.rw------- 1.6k postgres │ │ ├── ...
drwxr-x--- - redis │ └── redis
drwxr-x--- - redis │ ├── config
drwxr-x--- - redis │ │ ├── custom
.rw-r----- 109 redis │ │ │ ├── ...
.rw-r----- 1.5k redis │ │ ├── redis.conf
.rw-r----- 13k redis │ │ ├── source-full.conf
.rw-r----- 114k redis │ │ └── source.conf
drwx------ - redis │ └── tls
.rw------- 1.9k redis │ ├── ...
drwxr-xr-x - root ├── logs
drwxr-x--- - mysql │ ├── mysql
drwxr-x--- - mysql │ │ └── binlog
drwxr-x--- - nginx │ ├── nginx
drwxr-x--- - nginx │ │ ├── access
drwxr-x--- - nginx │ │ └── error
drwxr-x--- - php │ ├── php
drwxr-x--- - postgres │ ├── postgres
.rw-r----- 53k postgres │ │ ├── postgres-09.json
.rw-r----- 1.0k postgres │ │ ├── postgres-09.log
.rw------- 2.8k postgres │ │ ├── ...
drwxr-x--- - postgres │ │ └── wal_archive
.rw------- 17M postgres │ │ ├── ...
drwxr-x--- - redis │ └── redis
drwxr-xr-x - redis │ ├── rdbData
.rw-r----- 102 redis │ │ └── dump.rdb
.rw-r----- 5.5k redis │ ├── redis-server.log
.rw-r----- 5.5k redis │ ├── redis-server.log-20260208.1770554537
.rw-r----- 5.5k redis │ ├── ...
drwxr-x--- - mysql ├── mysql
drwxr-x--- - nginx ├── nginx
drwxr-xr-x - root ├── ohmyzsh
drwxr-xr-x - root │ ├── ...
drwx------ - postgres ├── pgData
drwx------ - postgres │ ├── ...
.rw------- 723 postgres │ ├── pg_hba.conf
.rw------- 5.7k postgres │ ├── pg_hba.conf.bak
.rw------- 193 postgres │ ├── pg_ident.conf
.rw------- 2.7k postgres │ ├── pg_ident.conf.bak
.rw------- 3 postgres │ ├── PG_VERSION
drwx------ - postgres │ ├── pg_wal
.rw------- 17M postgres │ │ ├── 000000010000000000000007
.rw------- 17M postgres │ │ ├── ...
drwx------ - postgres │ │ ├── archive_status
drwx------ - postgres │ │ └── summaries
.rw------- 88 postgres │ ├── postgresql.auto.conf
.rw------- 35k postgres │ ├── postgresql.conf
.rw------- 33k postgres │ ├── postgresql.conf.bak
.rw------- 52 postgres │ ├── postmaster.opts
.rw------- 88 postgres │ └── postmaster.pid
drwxr-x--- - php ├── php
drwxr-x--- - php │ └── 85
drwxr-x--- - postgres ├── postgres
drwxr-x--- - postgres │ ├── ...
drwxr-x--- - redis ├── redis
drwxr-x--- - redis │ └── bin
.rwxr-x--- 6.6M redis │ ├── redis-benchmark
lrwxrwxrwx - redis │ ├── redis-check-aof -> redis-server
lrwxrwxrwx - redis │ ├── redis-check-rdb -> redis-server
.rwxr-x--- 7.5M redis │ ├── redis-cli
lrwxrwxrwx - redis │ ├── redis-sentinel -> redis-server
.rwxr-x--- 20M redis │ └── redis-server
drwxr-x--- - nginx ├── sites
drwxr-x--- - nginx │ ├── available
drwxr-x--- - nginx │ ├── enabled
drwxr-x--- - nginx │ └── tls
drwxr-x--- - sqlite3 ├── sqlite3
drwxr-x--- - sqlite3 │ ├── bin
.rwxr-x--- 7.3M sqlite3 │ │ └── sqlite3
drwxr-x--- - sqlite3 │ ├── include
.rw-r----- 672k sqlite3 │ │ ├── sqlite3.h
.rw-r----- 39k sqlite3 │ │ └── sqlite3ext.h
drwxr-x--- - sqlite3 │ ├── lib
.rw-r----- 8.9M sqlite3 │ │ ├── libsqlite3.a
lrwxrwxrwx - sqlite3 │ │ ├── libsqlite3.so -> libsqlite3.so.3.51.2
lrwxrwxrwx - sqlite3 │ │ ├── libsqlite3.so.0 -> libsqlite3.so.3.51.2
.rw-r----- 4.9M sqlite3 │ │ ├── libsqlite3.so.3.51.2
drwxr-x--- - sqlite3 │ │ └── pkgconfig
.rw-r----- 275 sqlite3 │ │ └── sqlite3.pc
drwxr-x--- - sqlite3 │ └── share
drwxr-x--- - sqlite3 │ └── ...
.rw-r--r-- 0 root └── ...一键脚本
这几个脚本可以快速创建、授权目录,清理系统缓存。
zsh
#!/usr/bin/env bash
# 用户列表
users=(
"2001:sqlite3"
"2002:redis"
"2003:postgres"
"2005:php"
"2006:nginx"
"2007:mysql"
);
# 函数定义
funcCreateUser() {
local uid username
IFS=':' read -r uid username <<< "$1"
echo "正在创建用户: $username (UID: $uid)"
groupadd -g $uid $username
useradd -c "$username related process user" \
-g $username -u $uid -s /sbin/nologin -m $username
cp -r /root/.zshrc /home/$username
chown $username:$username -R /home/$username/.zshrc
ln -s /server/ohmyzsh /home/$username/.oh-my-zsh
}
# 主循环
for user in "${users[@]}"; do
funcCreateUser "$user"
done
# 用户与组的关系
usermod -a -G postgres,sqlite3 php
usermod -a -G sqlite3,redis,postgres,php,nginx,mysql emad
# 开发者创建的文件 [nginx 工作进程用户] 和 [php 工作进程用户] 需要能读取
usermod -a -G emad nginx
usermod -a -G emad phpzsh
#!/usr/bin/env bash
items=(
'/www'
'/server'
'/server/default'
'/server/logs'
'/server/etc'
'/server/sqlite3'
'/server/redis'
'/server/logs/redis'
'/server/logs/redis/rdbData'
'/server/etc/redis'
'/server/etc/redis/tls'
'/server/etc/redis/config'
'/server/etc/redis/config/custom'
'/server/postgres'
'/server/pgData'
'/server/logs/postgres'
'/server/logs/postgres/wal_archive'
'/server/etc/postgres'
'/server/etc/postgres/tls'
'/server/php'
'/server/php/85'
'/server/logs/php'
'/server/etc/php'
'/server/etc/php/tools'
'/server/etc/php/85'
'/server/etc/php/85/php-fpm.d'
'/server/nginx'
'/server/logs/nginx'
'/server/logs/nginx/access'
'/server/logs/nginx/error'
'/server/etc/nginx'
'/server/etc/nginx/custom'
'/server/mysql'
'/server/data'
'/server/logs/mysql'
'/server/logs/mysql/binlog'
'/server/etc/mysql'
'/server/sites'
'/server/sites/tls'
'/server/sites/available'
'/server/sites/enabled'
)
# 主循环
for item in "${items[@]}"; do
if [ ! -d "$item" ]; then
mkdir -p "$item"
fi
donezsh
#!/usr/bin/env bash
FuncRunPower(){
local DirPerm filePerm
# 判断权限
if [[ "$2" == "root" ]]; then
DirPerm=755
filePerm=644
else
DirPerm=750
filePerm=640
fi
chown "$2":"$2" -R "$1"
find "$1" -type d -exec chmod $DirPerm {} \;
find "$1" -type f -exec chmod $filePerm {} \;
echo "目录 $1 权限已设置为 目录:$DirPerm 文件:$filePerm"
}
rootItems=(
'/server'
);
wwwItems=(
'/www'
);
sqlite3Items=(
'/server/sqlite3'
);
redisItems=(
'/server/redis'
'/server/logs/redis'
'/server/etc/redis'
);
postgresItems=(
'/server/postgres'
'/server/pgData'
'/server/logs/postgres'
'/server/etc/postgres'
);
phpItems=(
'/server/php'
'/server/logs/php'
'/server/etc/php'
);
nginxItems=(
'/server/nginx'
'/server/logs/nginx'
'/server/etc/nginx'
'/server/sites'
);
mysqlItems=(
'/server/mysql'
'/server/data'
'/server/logs/mysql'
'/server/etc/mysql'
);
# 循环
for item in "${rootItems[@]}"; do
FuncRunPower "$item" 'root'
done
for item in "${wwwItems[@]}"; do
FuncRunPower "$item" 'emad'
done
for item in "${sqlite3Items[@]}"; do
FuncRunPower "$item" 'sqlite3'
done
for item in "${redisItems[@]}"; do
FuncRunPower "$item" 'redis'
done
for item in "${postgresItems[@]}"; do
FuncRunPower "$item" 'postgres'
done
for item in "${phpItems[@]}"; do
FuncRunPower "$item" 'php'
done
for item in "${nginxItems[@]}"; do
FuncRunPower "$item" 'nginx'
done
for item in "${mysqlItems[@]}"; do
FuncRunPower "$item" 'mysql'
donezsh
#!/usr/bin/env bash
printf "\033c"
echo_cyan(){
printf '\033[1;36m%b\033[0m\n' "$@"
}
echo_green(){
printf '\033[1;32m%b\033[0m\n' "$@"
}
echo_red(){
printf '\033[1;31m%b\033[0m\n' "$@"
}
echo_yellow(){
printf '\033[1;33m%b\033[0m\n' "$@"
}
echo_cyan "删除/var/cache/apt/archives/下所有包文件"
apt clean
echo_cyan "仅删除过期的缓存文件"
apt autoclean
echo_cyan "删除不再被依赖的软件包"
apt autoremove --purge
echo_cyan "立即清空日志"
rm -rf /var/log/*
echo_cyan "是否清理zsh_history文件(1清理/默认不清理):"
read num
if [[ "$num" = "1" ]]; then
echo_yellow "开始清理终端历史文件文件"
rm /home/{sqlite3,redis,postgres,php,nginx,mysql,emad}/.{zsh,bash}_history
rm /home/{sqlite3,redis,postgres,php,nginx,mysql,emad}/.{z,viminfo}
rm /home/{sqlite3,redis,postgres,php,nginx,mysql,emad}/.zcompdump-*
rm /root/.{zsh,bash}_history
rm /root/.{z,viminfo}
rm /root/.zcompdump-*
echo_yellow "清理终端历史文件结束"
else
echo_yellow "不清理 .zsh_history 文件"
fi
echo_red "警告⚠️:请谨慎执行此脚本!!!"
echo_yellow "清理日志需停止服务"
echo_cyan "是否清理lnmpp日志(1清理/默认不清理):"
read num1
if [ "$num1" = "1" ]; then
echo_green "先停止服务"
systemctl stop {redis,postgres,php85-fpm,nginx,mysqld}.service
echo_green "开始清理redis日志"
find /server/logs/redis/ -maxdepth 1 -type f -exec rm {} \;
echo_green "开始清理postgres日志"
find /server/logs/postgres/ -maxdepth 1 -type f -exec rm {} \;
echo_green "开始清理php日志"
find /server/logs/php/ -type f -exec rm {} \;
echo_green "开始清理nginx默认日志目录"
find /server/nginx/logs/ -type f -exec rm {} \;
echo_green "开始清理nginx错误日志"
find /server/logs/nginx/error/ -type f -exec rm {} \;
echo_green "开始清理nginx访问日志"
find /server/logs/nginx/access/ -type f -exec rm {} \;
echo_green "开始清理mysql错误日志"
find /server/logs/mysql/ -type f -exec rm {} \;
echo_green "清理lnmpp日志完成"
else
echo_yellow "不清理lnmpp日志"
fi
echo_red "警告⚠️:请谨慎执行此脚本!!!"
echo_cyan "是否清理二进制日志(1清理/默认不清理):"
read num2
if [ "$num2" = "1" ]; then
echo_green "先停止服务"
systemctl stop {redis,postgres,php85-fpm,nginx,mysqld}.service
echo_green "开始清理PostgreSQL预写式日志(已归档)"
rm /server/logs/postgres/wal_archive/*
# echo_green "开始清理PostgreSQL预写式日志(当前不可删除)"
# find /server/pgData/pg_wal/ -maxdepth 1 -type f -exec rm {} \;
echo_green "开始清理MySQL二进制日志"
rm /server/logs/mysql/binlog/*
echo_green "清理lnpp日志完成"
else
echo_yellow "不清理数据库二进制日志"
fi
echo_cyan "是否清理Redis本地存储(1清理/默认不清理):"
read num3
if [[ "$num3" = "1" ]]; then
echo_yellow "开始清理Redis本地存储"
find /server/logs/redis/rdbData/ -type f -exec rm {} \;
# find /server/logs/redis/rdbData/ -maxdepth 1 -type f -exec rm {} \;
# find /server/logs/redis/rdbData/appendonlydir/ -maxdepth 1 -type f -exec rm {} \;
echo_yellow "清理Redis本地存储结束"
else
echo_yellow "不清理Redis本地存储"
fi
echo_cyan "是否启动服务(1启动/默认不启动):"
read num2
if [ "$num2" = "1" ]; then
systemctl start {redis,postgres,php85-fpm,nginx,mysqld}.service
echo_green "服务已重新启动"
else
echo_yellow "未重启服务,请手动启动"
fi编译套件
这些包是编译软件时最常用到的依赖项
bash
apt install --no-install-recommends \
build-essential autoconf pkg-config -ybash
apt install --no-install-recommends \
tcl -ybash
apt install --no-install-recommends \
libsystemd-dev libssl-dev -ybash
apt install --no-install-recommends \
llvm-dev clang libicu-dev liblz4-dev libzstd-dev liburing-dev \
bison flex libreadline-dev zlib1g-dev uuid-dev -ybash
apt install --no-install-recommends \
libcurl4-openssl-dev libpng-dev libjpeg-dev libfreetype-dev \
libonig-dev libsodium-dev libargon2-dev -ybash
apt install --no-install-recommends \
libxslt1-dev libgd-dev libgeoip-dev -ybash
apt install --no-install-recommends \
cmake libtirpc-dev -y