From 85eb70fc633d34f7df04f4167f11c388f4105855 Mon Sep 17 00:00:00 2001 From: smail Date: Sat, 17 Oct 2026 15:14:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=83=A8=E7=BD=B2=E4=B8=8E?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E8=84=9A=E6=9C=AC=EF=BC=9A=E5=85=A8=E6=96=B0?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E4=BB=A5=E8=A7=A3=E5=8E=8B=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E4=B8=BA=E5=AE=89=E8=A3=85=E8=B7=AF=E5=BE=84=EF=BC=8C=E5=B9=B3?= =?UTF-8?q?=E6=BB=91=E6=9B=B4=E6=96=B0=E4=BB=A5=E7=B3=BB=E7=BB=9F=E5=B7=B2?= =?UTF-8?q?=E6=9C=89=E5=AE=89=E8=A3=85=E8=B7=AF=E5=BE=84=E4=B8=BA=E7=9B=AE?= =?UTF-8?q?=E6=A0=87=E6=9B=B4=E6=96=B0=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/install-systemd.sh | 2 +- deploy/update-systemd.sh | 69 +++++++++++++++++++++++++++------------ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/deploy/install-systemd.sh b/deploy/install-systemd.sh index 3d6d8dfa..a87a4b1f 100644 --- a/deploy/install-systemd.sh +++ b/deploy/install-systemd.sh @@ -130,7 +130,7 @@ for legacy_backup in /var/backups/smail-deploy-*; do done if [ "$fresh" = true ]; then if [ -d "$runtime_dir" ] && [ -n "$(find "$runtime_dir" -mindepth 1 -maxdepth 1 -type l -print -quit)" ]; then - echo "全新部署已停止:/opt/smail 顶层存在符号链接,拒绝清理。" >&2 + echo "全新部署已停止:$runtime_dir 顶层存在符号链接,拒绝清理。" >&2 exit 1 fi diff --git a/deploy/update-systemd.sh b/deploy/update-systemd.sh index 83009c37..f78b25df 100644 --- a/deploy/update-systemd.sh +++ b/deploy/update-systemd.sh @@ -2,11 +2,14 @@ set -eu # Smail 生产环境版本平滑升级脚本 -# 仅更新程序文件与系统服务,严禁清空数据库、配置文件、证书或域名配置,无需重新走初始化流程。 +# 规则说明: +# 1. 严格以现有生产环境的实际安装路径作为更新路径,严禁以升级包解压所在路径作为运行路径。 +# 2. 仅更新程序文件与系统服务,严密保留现有数据库、配置文件、证书与域名,免去重新初始化流程。 usage() { - echo "用法:$0 [安装根目录]" - echo "如果不指定安装目录,将自动从现有的 smail.service 中读取,或默认为脚本上级目录。" + echo "用法:$0 [现有安装目录]" + echo "默认将自动从 /etc/systemd/system/smail.service 中解析实际安装路径(如 /smail 或 /opt/smail)。" + echo "如果服务未安装或需要手动指定,可在参数中显式传入安装目录。" } if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then @@ -22,11 +25,13 @@ fi script_dir="$(cd "$(dirname "$0")" && pwd)" package_root="$(realpath -e -- "$script_dir/..")" -# 1. 自动识别安装目标目录 +# 1. 自动探查并确定系统的实际安装路径(严禁使用当前升级包的解压路径) target_dir="${1:-}" + if [ -z "$target_dir" ]; then + # 优先从 smail.service 中读取 WorkingDirectory if [ -f /etc/systemd/system/smail.service ]; then - service_workdir="$(grep -E '^WorkingDirectory=' /etc/systemd/system/smail.service | head -n1 | cut -d'=' -f2- | tr -d ' ' || true)" + service_workdir="$(grep -E '^[[:space:]]*WorkingDirectory=' /etc/systemd/system/smail.service | head -n1 | cut -d'=' -f2- | tr -d ' ' || true)" if [ -n "$service_workdir" ] && [ -d "$service_workdir" ]; then target_dir="$service_workdir" fi @@ -34,20 +39,36 @@ if [ -z "$target_dir" ]; then fi if [ -z "$target_dir" ]; then - target_dir="$package_root" + # 其次检查常见的默认安装目录 + for candidate in /smail /opt/smail; do + if [ -d "$candidate" ] && [ -f "$candidate/smail" ] && [ "$candidate" != "$package_root" ]; then + target_dir="$candidate" + break + fi + done +fi + +if [ -z "$target_dir" ]; then + echo "错误:未能在系统服务中检测到 Smail 的现有安装路径!" >&2 + echo "请手动指定目标安装目录,例如:$0 /smail" >&2 + exit 1 fi target_dir="$(realpath -m -- "$target_dir")" if [ ! -d "$target_dir" ]; then - echo "错误:目标目录不存在: $target_dir" >&2 + echo "错误:目标安装目录不存在: $target_dir" >&2 exit 1 fi +if [ ! -f "$target_dir/smail" ]; then + echo "警告:在目标目录 $target_dir 下未检测到旧的 smail 主程序,请确认是否为正确的安装目录!" +fi + echo "==========================================================" -echo " Smail 服务平滑升级 " -echo " 升级包路径: $package_root" -echo " 目标安装目录: $target_dir" +echo " Smail 服务平滑更新 " +echo " 升级包解压源目录 : $package_root" +echo " 目标系统安装目录 : $target_dir" echo "==========================================================" case "$(uname -m)" in @@ -56,7 +77,7 @@ case "$(uname -m)" in *) echo "不支持的系统架构: $(uname -m)" >&2; exit 1 ;; esac -# 2. 定位新版本程序二进制 +# 2. 定位新版本程序二进制文件 if [ -f "$package_root/smail" ] && [ -f "$package_root/smail-admin" ] && [ -f "$package_root/smail-config" ]; then new_smail="$package_root/smail" new_smail_admin="$package_root/smail-admin" @@ -66,7 +87,7 @@ elif [ -f "$package_root/out/backend/smail_linux_$arch" ]; then new_smail_admin="$package_root/out/backend/smail-admin_linux_$arch" new_smail_config="$package_root/out/backend/smail-config_linux_$arch" else - echo "错误:未能找到有效的升级二进制程序文件!" >&2 + echo "错误:未能找到升级包中的二进制程序文件!" >&2 exit 1 fi @@ -77,7 +98,7 @@ for bin in "$new_smail" "$new_smail_admin" "$new_smail_config"; do fi done -# 3. 停止正在运行的服务 +# 3. 停止运行中的服务以解除文件占用 echo ">>> 正在停止运行中的 Smail 服务..." systemctl stop smail.service 2>/dev/null || true systemctl stop smail-admin.service 2>/dev/null || true @@ -90,8 +111,8 @@ if ! getent passwd smail >/dev/null; then useradd --system --gid smail --home-dir "$target_dir" --shell /usr/sbin/nologin smail fi -# 5. 替换程序二进制文件(设置正确属主与权限,防止覆盖自身报错) -echo ">>> 正在更新可执行程序..." +# 5. 替换程序二进制文件至安装目录(保持安装目录独立,防止覆盖自身报错) +echo ">>> 正在更新主程序及管理工具至: $target_dir" if [ "$new_smail" != "$target_dir/smail" ]; then cp -f "$new_smail" "$target_dir/smail" fi @@ -110,15 +131,22 @@ fi chown root:root "$target_dir/smail-config" chmod 0700 "$target_dir/smail-config" -# 6. 更新 systemd 服务单元 +# 同时更新安装目录下的 deploy 脚本供日后维护 +if [ "$package_root" != "$target_dir" ] && [ -d "$package_root/deploy" ]; then + mkdir -p "$target_dir/deploy" + cp -rf "$package_root/deploy"/* "$target_dir/deploy/" 2>/dev/null || true + chmod -R 0755 "$target_dir/deploy" 2>/dev/null || true +fi + +# 6. 更新 systemd 服务单元(配置安装路径为工作目录) systemd_src="$package_root/deploy/systemd" if [ ! -d "$systemd_src" ] && [ -d "$target_dir/deploy/systemd" ]; then systemd_src="$target_dir/deploy/systemd" fi if [ -f "$systemd_src/smail.service" ]; then - sed -e "s|WorkingDirectory=/opt/smail|WorkingDirectory=$target_dir|g" \ - -e "s|ExecStart=/opt/smail/smail|ExecStart=$target_dir/smail|g" \ + sed -e "s|WorkingDirectory=[^ ]*|WorkingDirectory=$target_dir|g" \ + -e "s|ExecStart=[^ ]*/smail|ExecStart=$target_dir/smail|g" \ -e "s|/opt/smail/config|$target_dir/config|g" \ -e "s|/opt/smail/data|$target_dir/data|g" \ -e "s|/opt/smail/ssl|$target_dir/ssl|g" \ @@ -130,8 +158,8 @@ if [ -f "$systemd_src/smail.service" ]; then fi if [ -f "$systemd_src/smail-admin.service" ]; then - sed -e "s|WorkingDirectory=/opt/smail|WorkingDirectory=$target_dir|g" \ - -e "s|ExecStart=/opt/smail/smail-admin|ExecStart=$target_dir/smail-admin|g" \ + sed -e "s|WorkingDirectory=[^ ]*|WorkingDirectory=$target_dir|g" \ + -e "s|ExecStart=[^ ]*/smail-admin|ExecStart=$target_dir/smail-admin|g" \ "$systemd_src/smail-admin.service" > /etc/systemd/system/smail-admin.service chmod 0644 /etc/systemd/system/smail-admin.service chown root:root /etc/systemd/system/smail-admin.service @@ -148,6 +176,7 @@ sleep 1 if systemctl is-active --quiet smail.service; then echo "==========================================================" echo " Smail 平滑升级成功!" + echo " 升级程序写入目录: $target_dir" echo " 数据库、SSL 证书及域名配置均完整保留。" echo " 服务状态: active (running)" echo "=========================================================="