lnmp.org 编译环境 → Debian apt 无缝迁移教程

lnmp.org 编译环境 → Debian apt 无缝迁移教程

原创内容,转载请注明出处:https://www.myzhenai.com.cn/post/5135.html

因为PHP曝发了严重的 编号:CVE-2026-109618、CVE-2026-109619 0-day(零日)安全漏洞,所以必须要升级系统内的PHP安全补丁,

我有几台服务器,其他的服务器都是用的apt安装的php、nginx、mysql等环境,并且系统上有安装自动更新脚本,系统会自动更新安全补丁

我最担心的是其中一台服务器,因为是以前用军哥的lnmp一键安装脚本安装的服务环境,并且安装面板现在已经不支持高版本的php、nginx、mysql等服务器环境了

并且我安装完,就把lnmp安装包删除了,只留下一下lnmp程序,也不能通过脚本自带的upgrade.sh来升级了

我想,倒不如把lnmp服务环境卸载了,改装成系统自己库里的安装方式,但我又不想重装服务器,怎么办?

于是,我列出一个步骤,按照步骤一步一步来执行。

一、整理计划,列出需要备份的文件
1、备份nginx网站信息,免得重新配置网站的信息
2、备份PHP设置信息
3、备份mysql数据库信息
4、备份ssl证书
5、备份一些运维脚本

BK="/root/server-backup-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BK"/{nginx,php,mysql,ssl,acme,cron,scripts,misc}
echo "$BK" > /root/server-backup-LATEST.path

# apt
tar -C /etc -czf "$BK/nginx/etc-nginx.tar.gz" nginx
cp -a /etc/nginx/sites-available "$BK/nginx/sites-available" 2>/dev/null || true
cp -a /etc/nginx/sites-enabled "$BK/nginx/sites-enabled" 2>/dev/null || true
nginx -T > "$BK/nginx/nginx-T.txt" 2>&1 || true

# 若仍是 LNMP:
# tar -C /usr/local/nginx -czf "$BK/nginx/nginx-conf.tar.gz" conf
# cp -a /usr/local/nginx/conf "$BK/nginx/conf-copy"

# apt(8.3)
tar -C /etc -czf "$BK/php/etc-php.tar.gz" php
php -i > "$BK/php/php-i.txt" 2>&1
php -m > "$BK/php/php-modules.txt" 2>&1
cp -a /etc/php/8.3/fpm/pool.d "$BK/php/pool.d" 2>/dev/null || true

# LNMP:
# tar -C /usr/local/php -czf "$BK/php/php-etc.tar.gz" etc

# 逻辑备份(必做)
mysqldump -uroot -p --all-databases --single-transaction \
  --routines --triggers --events --hex-blob \
  | gzip -c > "$BK/mysql/all-databases.sql.gz"

# 配置
cp -a /etc/mysql "$BK/mysql/etc-mysql" 2>/dev/null || true
# 或:cp -a /etc/my.cnf /etc/mysql/my.cnf* "$BK/mysql/" 2>/dev/null || true

mysql -uroot -p -e "SHOW DATABASES;" > "$BK/mysql/databases.txt"

# 线上证书(apt)
cp -a /etc/nginx/ssl "$BK/ssl/nginx-ssl" 2>/dev/null || true

# acme 账户与续签状态(强烈建议)
tar -C /root -czf "$BK/acme/dot-acme.sh.tar.gz" .acme.sh

# LNMP 旧路径若还在:
# cp -a /usr/local/nginx/conf/ssl "$BK/ssl/lnmp-ssl" 2>/dev/null || true
# cp -a /usr/local/nginx/cert "$BK/ssl/lnmp-cert" 2>/dev/null || true

我们需要先将这些配置信息备份到一个我们重装环境不会影响到的地方,特别是nginx网站设置和ssl签约证书,如果我们不做备份的话,那么装好环境后我们还要重新设置

二、导出站点地图

1、把每个 vhost 的 server_name、root、是否 443、证书路径、PHP 处理方式列成表,接下来按表恢复,避免漏站。

VHOST_DIR=/usr/local/nginx/conf/vhost
OUT=/root/vhost-map-$(date +%Y%m%d-%H%M%S).txt

{
  echo "生成时间: $(date '+%F %T')"
  echo "配置目录: $VHOST_DIR"
  echo
  printf "%-28s | %-40s | %-6s | %-55s | %s\n" \
    "server_name" "root" "HTTPS" "ssl_certificate" "php/fastcgi"
  printf "%s\n" "-----------------------------+------------------------------------------+--------+---------------------------------------------------------+----------------"

  for f in "$VHOST_DIR"/*.conf; do
    [[ -f "$f" ]] || continue
    [[ "$f" == *.bak* ]] && continue

    # 每个 conf 可能有多个 server{},按 server 块粗分
    awk -v file="$f" '
      /server[[:space:]]*\{/ { in_server=1; names=""; root=""; listen443=0; cert=""; php=""; next }
      in_server && /listen[[:space:]]+.*443/ { listen443=1 }
      in_server && $1=="server_name" {
        line=$0; sub(/^[[:space:]]*server_name[[:space:]]+/, "", line); sub(/;.*/, "", line);
        gsub(/[[:space:]]+/, " ", line); names=line
      }
      in_server && $1=="root" {
        root=$2; gsub(/;/, "", root)
      }
      in_server && $1=="ssl_certificate" {
        cert=$2; gsub(/;/, "", cert)
      }
      in_server && /fastcgi_pass/ {
        php=$0; gsub(/^[[:space:]]+/, "", php); gsub(/;/, "", php)
      }
      in_server && /include[[:space:]]+.*enable-php/ {
        if (php=="") php=$0; gsub(/^[[:space:]]+/, "", php); gsub(/;/, "", php)
      }
      in_server && /^[[:space:]]*\}/ {
        if (names != "") {
          https = (listen443 ? "yes" : "no")
          if (cert=="") cert="-"
          if (php=="") php="-"
          if (root=="") root="-"
          printf "%-28s | %-40s | %-6s | %-55s | %s\n", names, root, https, cert, php
        }
        in_server=0; names=""; root=""; listen443=0; cert=""; php=""
      }
    ' "$f"

    echo "  # 来源文件: $f"
  done
} | tee "$OUT"

echo
echo "已写入: $OUT"

这个是自动识别我们服务器里的nginx网站设置里,识别出我们服务器上的所有网站和网站配置信息,方便下一步我们按照这个表来进行工作

三、停止服务器

lnmp stop
# 注意:个别环境 lnmp stop 停不干净 MySQL,需 systemctl / 手动确认端口

四、卸载lnmp安装环境
lnmp-uninstall-only/
├── uninstall.sh          ← 必须(卸载入口)
├── lnmp.conf             ← 必须(uninstall 会 source)
└── include/
    ├── main.sh           ← 必须(Check_DB / Remove_StartUp 等)
    └── version.sh        ← 建议带上(保险)

从你的lnmp脚本安装包里,将这几个脚配文件和conf文件,复制到一个新的目录下,就按照这个层级来存放,并把这目录和文件上传到服务器上,我们需要运行lnmp的卸载脚本来卸载
cd /tmp/lnmp-uninstall-only
ls uninstall.sh lnmp.conf include/main.sh
bash uninstall.sh
# 选 1 = 卸载 LNMP

五、apt安装新的服务
apt-get update
apt-get install -y curl ca-certificates gnupg2 lsb-release apt-transport-https
apt-get install -y nginx

nginx -v
systemctl enable nginx
systemctl start nginx   # 若端口仍被占用,可先 enable,最后 再 start

1、先安装nginx
curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg

echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" \
  > /etc/apt/sources.list.d/php-sury.list

apt-get update

apt-get install -y \
  php8.3-cli php8.3-fpm php8.3-common \
  php8.3-mysql php8.3-xml php8.3-mbstring php8.3-curl \
  php8.3-gd php8.3-zip php8.3-opcache php8.3-readline

# 按站点需要追加,例如:
# apt-get install -y php8.3-imagick php8.3-intl php8.3-bcmath php8.3-soap

php -v
systemctl enable --now php8.3-fpm
ls -l /run/php/php8.3-fpm.sock

2、接着安装PHP
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
systemctl reload php8.3-fpm

3、设置用户和用户组,因为lnmp默认使用的是www:www这样的用户和用户组,所以在这里我们也要按照这样来设置
# 若尚无 www 用户则创建(已有可跳过)
id www >/dev/null 2>&1 || useradd -r -s /usr/sbin/nologin -d /var/www -M www

# PHP-FPM 池
sed -i -E \
  's/^(user|group|listen\.owner|listen\.group) = www-data/\1 = www/' \
  /etc/php/8.3/fpm/pool.d/www.conf

grep -E '^(user|group|listen\.owner|listen\.group)' /etc/php/8.3/fpm/pool.d/www.conf

# Nginx
# 将 nginx.conf 中的 user 行改为:
#   user www www;
sed -i -E 's/^user\s+.*/user www www;/' /etc/nginx/nginx.conf
grep -E '^user' /etc/nginx/nginx.conf

systemctl restart php8.3-fpm
nginx -t && systemctl reload nginx

4、接下来安装mysql
# 使用现行 MySQL 官方 GPG 密钥(旧密钥可能过期导致 apt update 失败)
curl -fsSL https://repo.mysql.com/RPM-GPG-KEY-mysql-2025 \
  | gpg --dearmor -o /usr/share/keyrings/mysql-archive-keyring.gpg

CODENAME="$(lsb_release -sc)"
cat >/etc/apt/sources.list.d/mysql.list <<EOF
deb [signed-by=/usr/share/keyrings/mysql-archive-keyring.gpg] http://repo.mysql.com/apt/debian ${CODENAME} mysql-8.0
deb [signed-by=/usr/share/keyrings/mysql-archive-keyring.gpg] http://repo.mysql.com/apt/debian ${CODENAME} mysql-tools
EOF

apt-get update
apt-get install -y mysql-community-server

systemctl enable --now mysql
mysql -V
mysql -uroot -p -e "SELECT VERSION();"

如果你的系统是debina的时候,安装时要注意
不要装成 MariaDB
Debian 的 default-mysql-server 往往会拉 MariaDB。要 Oracle MySQL 就用官方源装 mysql-community-server。

官方源 GPG 密钥
旧密钥过期会导致 apt update 失败(EXPKEYSIG)。用现行官方密钥再装。

先空实例,再导业务数据
装好后先确认能 mysql -uroot -p 登录,再导入。

不要把旧 LNMP 的物理数据目录直接接到新实例
用 mysqldump 逻辑备份恢复,不要整目录替换 datadir。

用命令挨个库的导入,不要整个库导入。

mysqldump -uroot -p --single-transaction --routines --triggers --databases 库名 \
  | gzip -c > 库名.sql.gz

这几项全部装完后用命令检查一下!
nginx -v
php -v
mysql -V

systemctl is-active nginx php8.3-fpm mysql
systemctl is-enabled nginx php8.3-fpm mysql

ls -l /run/php/php8.3-fpm.sock
id www

六、恢复站点、库、证书
vhost 迁到 /etc/nginx/sites-available,证书路径改为 /etc/nginx/ssl/
保留旧 include 习惯时,可做 /etc/nginx/lnmp-compat/(如 anti-scan、rewrite、enable-php-pathinfo、fastcgi)
fastcgi_pass 指向 unix:/run/php/php8.3-fpm.sock

1、指定备份路径,就是前边我闪进行备份的路径,这里设置变量

BK="$(cat /root/server-backup-LATEST.path)"
echo "BK=$BK"
ls "$BK"

2、新建目录,有一些需要的目录我们需要在这里新建
mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled
mkdir -p /etc/nginx/ssl
mkdir -p /etc/nginx/lnmp-compat/rewrite
mkdir -p /root/old-nginx-conf

if [[ -f "$BK/nginx/nginx-conf.tar.gz" ]]; then
  tar -C /root/old-nginx-conf -xzf "$BK/nginx/nginx-conf.tar.gz"
  OLD_CONF=/root/old-nginx-conf/conf
elif [[ -d "$BK/nginx/conf-copy" ]]; then
  OLD_CONF="$BK/nginx/conf-copy"
else
  echo "未找到 nginx conf 备份"; exit 1
fi

echo "OLD_CONF=$OLD_CONF"
ls "$OLD_CONF/vhost"

3、查找lnmp兼容片段
for f in enable-php.conf enable-php-pathinfo.conf fastcgi.conf pathinfo.conf anti-scan.conf; do
  [[ -f "$OLD_CONF/$f" ]] && cp -a "$OLD_CONF/$f" /etc/nginx/lnmp-compat/
done
[[ -d "$OLD_CONF/rewrite" ]] && cp -a "$OLD_CONF/rewrite/." /etc/nginx/lnmp-compat/rewrite/

sed -i -E \
  's|fastcgi_pass[[:space:]]+127\.0\.0\.1:9000;|fastcgi_pass unix:/run/php/php8.3-fpm.sock;|g' \
  /etc/nginx/lnmp-compat/enable-php*.conf 2>/dev/null || true
sed -i -E \
  's|fastcgi_pass[[:space:]]+unix:/tmp/php-cgi\.sock;|fastcgi_pass unix:/run/php/php8.3-fpm.sock;|g' \
  /etc/nginx/lnmp-compat/enable-php*.conf 2>/dev/null || true

ls -la /etc/nginx/lnmp-compat/

4、主配置检查
grep -E '^user |sites-enabled' /etc/nginx/nginx.conf
# 确认有:user www www;
# 确认 http{} 内有:include /etc/nginx/sites-enabled/*;

rm -f /etc/nginx/sites-enabled/default

5、恢复站点信息,nginx的站点信息
for f in "$OLD_CONF"/vhost/*.conf; do
  [[ -f "$f" ]] || continue
  [[ "$f" == *.bak* ]] && continue
  cp -a "$f" "/etc/nginx/sites-available/$(basename "$f")"
done

for f in /etc/nginx/sites-available/*.conf; do
  sed -i \
    -e 's|/usr/local/nginx/conf/ssl/|/etc/nginx/ssl/|g' \
    -e 's|/usr/local/nginx/cert/|/etc/nginx/ssl/|g' \
    -e 's|include[[:space:]]\+rewrite/|include /etc/nginx/lnmp-compat/rewrite/|g' \
    -e 's|include[[:space:]]\+enable-php|include /etc/nginx/lnmp-compat/enable-php|g' \
    -e 's|include[[:space:]]\+fastcgi\.conf|include /etc/nginx/lnmp-compat/fastcgi.conf|g' \
    -e 's|include[[:space:]]\+anti-scan\.conf|include /etc/nginx/lnmp-compat/anti-scan.conf|g' \
    -e 's|fastcgi_pass[[:space:]]\+127\.0\.0\.1:9000;|fastcgi_pass unix:/run/php/php8.3-fpm.sock;|g' \
    -e 's|fastcgi_pass[[:space:]]\+unix:/tmp/php-cgi\.sock;|fastcgi_pass unix:/run/php/php8.3-fpm.sock;|g' \
    "$f"
done

for f in /etc/nginx/sites-available/*.conf; do
  ln -sfn "$f" "/etc/nginx/sites-enabled/$(basename "$f")"
done

ls -la /etc/nginx/sites-enabled/

6、恢复ssl证书
mkdir -p /etc/nginx/ssl

if [[ -d "$BK/nginx/cert-copy" ]]; then
  cp -a "$BK/nginx/cert-copy/." /etc/nginx/ssl/
elif [[ -f "$BK/nginx/nginx-cert.tar.gz" ]]; then
  tar -C /etc/nginx/ssl -xzf "$BK/nginx/nginx-cert.tar.gz"
elif [[ -d "$OLD_CONF/ssl" ]]; then
  cp -a "$OLD_CONF/ssl/." /etc/nginx/ssl/
else
  echo "未找到证书备份,请手动放入 /etc/nginx/ssl/"
fi

find /etc/nginx/ssl -type f | head -40

7、重启服务器环境
nginx -t

# 若旧 LNMP nginx 还在:
/usr/local/nginx/sbin/nginx -s quit 2>/dev/null || true
sleep 1

systemctl enable nginx
systemctl restart nginx
systemctl reload php8.3-fpm

systemctl is-active nginx php8.3-fpm mysql

七、防跨站设置,lnmp中的防跨站都是在网站根目录下新建一个.user.ini文件,但是转换到apt后,主要是在fastcgi中约定,现在为了兼容lnmp和apt,两个地方都做了设置

fastcgi配置

# 常见位置二选一(有哪个改哪个)
FCGI=""
[[ -f /etc/nginx/lnmp-compat/fastcgi.conf ]] && FCGI=/etc/nginx/lnmp-compat/fastcgi.conf
[[ -z "$FCGI" && -f /etc/nginx/fastcgi.conf ]] && FCGI=/etc/nginx/fastcgi.conf
[[ -n "$FCGI" ]] || { echo "未找到 fastcgi.conf,请指定路径"; exit 1; }

echo "使用: $FCGI"
cp -a "$FCGI" "${FCGI}.bak.$(date +%Y%m%d%H%M%S)"

# 删除旧的 open_basedir 行(含过宽的 /var/www/html)
sed -i '/PHP_ADMIN_VALUE.*open_basedir/d' "$FCGI"

# 收紧:仅本站 document_root + tmp/proc + MySQL sock
cat >> "$FCGI" <<'EOF'
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/:/run/mysqld/:/var/run/mysqld/";
EOF

grep open_basedir "$FCGI"
nginx -t && systemctl reload nginx
systemctl reload php8.3-fpm

.user.ini配置
# 自动遍历 /home/wwwroot 下一级目录(按实际结构改)
for d in /home/wwwroot/*/; do
  d="${d%/}"
  [[ -d "$d" ]] || continue
  # 跳过明显非站点目录(可按需增删)
  base=$(basename "$d")
  [[ "$base" == "logs" || "$base" == "default" ]] && continue

  chattr -i "$d/.user.ini" 2>/dev/null || true
  cat > "$d/.user.ini" <<EOF
open_basedir=${d}/:/tmp/:/proc/:/run/mysqld/:/var/run/mysqld/
EOF
  chown www:www "$d/.user.ini" 2>/dev/null || chown www-data:www-data "$d/.user.ini"
  chmod 644 "$d/.user.ini"
  chattr +i "$d/.user.ini"
  echo "---- $d/.user.ini ----"
  lsattr "$d/.user.ini"
  cat "$d/.user.ini"
done

到这一步,我们的服务器无缝迁移的工作就算完成了。大家可以重启一下环境。
nginx -t && systemctl reload nginx
systemctl reload php8.3-fpm

 

 

发布时 IP 属地:海南省海口市

IP 地址 216.73.217.151
区域位置 美国加利福尼亚
系统信息 🇨🇳 系统浏览器
最后修改:2026 年 10 月 22 日

赞赏支持

文章二维码