Smail/deploy/install-systemd.sh
smail 3532f76c66
Some checks are pending
Security Checks / security (push) Waiting to run
补充生产服务资源防护与只读预检并记录远程验收阻塞
2026-09-17 15:39:28 +08:00

117 lines
5.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -eu
if [ "$(id -u)" -ne 0 ]; then
echo "必须使用 root 用户安装 Smail" >&2
exit 1
fi
root_dir="$(realpath -e -- "${1:-$(dirname "$0")/..}")"
runtime_dir=/opt/smail
case "$(uname -m)" in
x86_64) arch=amd64 ;;
aarch64|arm64) arch=arm64 ;;
*) echo "不支持的系统架构" >&2; exit 1 ;;
esac
# 安装前先检查所有输入和运行状态,不能覆盖仍在运行的程序。
for file in "$root_dir/out/backend/smail_linux_$arch" "$root_dir/out/backend/smail-admin_linux_$arch" \
"$root_dir/deploy/systemd/smail.service" "$root_dir/deploy/systemd/smail-admin.service"; do
if [ ! -f "$file" ] || [ -L "$file" ] || [ ! -s "$file" ]; then
echo "安装输入不存在或不是普通文件:$file" >&2
exit 1
fi
done
if systemctl is-active --quiet smail.service || systemctl is-active --quiet smail-admin.service; then
echo "请先停止 Smail 主服务和管理员重置服务,安装不会自动中断现有业务。" >&2
exit 1
fi
for process in /proc/[0-9]*/exe; do
executable="$(readlink "$process" 2>/dev/null || true)"
case "$executable" in
"$runtime_dir/smail"|"$runtime_dir/smail (deleted)"|"$runtime_dir/smail-admin"|"$runtime_dir/smail-admin (deleted)")
echo "部署目录中的程序仍在运行,请确认并停止后再安装。" >&2
exit 1 ;;
esac
done
if [ -L /opt ] || [ -L "$runtime_dir" ] || { [ -e "$runtime_dir" ] && [ ! -d "$runtime_dir" ]; }; then
echo "部署路径不能是链接或普通文件。" >&2
exit 1
fi
for directory in config data ssl log plugins; do
target="$runtime_dir/$directory"
if [ -L "$target" ] || { [ -e "$target" ] && [ ! -d "$target" ]; }; then
echo "运行目录不能是链接或普通文件:$target" >&2
exit 1
fi
done
for target in "$runtime_dir/smail" "$runtime_dir/smail-admin" \
/etc/systemd/system/smail.service /etc/systemd/system/smail-admin.service \
/etc/smail/smail.env; do
if [ -L "$target" ] || { [ -e "$target" ] && [ ! -f "$target" ]; }; then
echo "程序或服务文件不能是链接或特殊文件:$target" >&2
exit 1
fi
done
if [ -L /etc/smail ] || { [ -e /etc/smail ] && [ ! -d /etc/smail ]; }; then
echo "服务环境目录不能是链接或普通文件:/etc/smail" >&2
exit 1
fi
if [ -L /run/smail ] || { [ -e /run/smail ] && [ ! -d /run/smail ]; }; then
echo "本机控制目录不能是链接或普通文件。" >&2
exit 1
fi
if [ -L /run/smail/admin-control.sock ] || { [ -e /run/smail/admin-control.sock ] && [ ! -S /run/smail/admin-control.sock ]; }; then
echo "本机控制路径不是安全套接字。" >&2
exit 1
fi
# 安装备份存放在系统备份目录,不在部署根目录遗留 .bak 文件。
backup_dir="$(mktemp -d /var/backups/smail-deploy-XXXXXXXX)"
for name in smail smail-admin; do
if [ -f "$runtime_dir/$name" ]; then cp -p -- "$runtime_dir/$name" "$backup_dir/$name"; fi
done
for name in smail.service smail-admin.service; do
if [ -f "/etc/systemd/system/$name" ]; then cp -p -- "/etc/systemd/system/$name" "$backup_dir/$name"; fi
done
if [ -f /etc/smail/smail.env ]; then cp -p -- /etc/smail/smail.env "$backup_dir/smail.env"; fi
if ! getent group smail >/dev/null; then groupadd --system smail; fi
if ! getent passwd smail >/dev/null; then useradd --system --gid smail --home-dir "$runtime_dir" --shell /usr/sbin/nologin smail; fi
install -d -o root -g root -m 0755 "$runtime_dir"
install -d -o root -g root -m 0750 /etc/smail
if [ ! -e /etc/smail/smail.env ]; then
# 只为新部署设置回收预算;已存在的文件始终保留部署人员的自定义环境配置。
umask 0077
printf '%s\n' 'SMAIL_ROOT=/opt/smail' 'GOMEMLIMIT=256MiB' > /etc/smail/smail.env
fi
chown root:root /etc/smail/smail.env
chmod 0600 /etc/smail/smail.env
for directory in config data ssl log plugins; do
target="$runtime_dir/$directory"
# 内置插件在临时沙箱中展开,只兼容已存在的历史插件目录。
if [ "$directory" = plugins ] && [ ! -d "$target" ]; then continue; fi
install -d -o smail -g smail -m 0700 "$target"
# 不跟随链接,也不越过挂载点;仅为本部署的存量运行数据调整属主。
find -P "$target" -xdev \( -type d -o -type f \) -exec chown --no-dereference smail:smail {} +
done
install -d -o smail -g smail -m 0750 /run/smail
if [ -S /run/smail/admin-control.sock ]; then
# 从旧版 root 主服务迁移时保留残留套接字,由主程序验证失活后自行处理。
chown --no-dereference smail:smail /run/smail/admin-control.sock
fi
install -d -o root -g root -m 0755 /run/systemd/ask-password
install -o root -g root -m 0755 "$root_dir/out/backend/smail_linux_$arch" "$runtime_dir/smail"
install -o root -g root -m 0700 "$root_dir/out/backend/smail-admin_linux_$arch" "$runtime_dir/smail-admin"
install -o root -g root -m 0644 "$root_dir/deploy/systemd/smail.service" /etc/systemd/system/smail.service
install -o root -g root -m 0644 "$root_dir/deploy/systemd/smail-admin.service" /etc/systemd/system/smail-admin.service
systemctl daemon-reload
systemctl enable smail
# 清理旧版本可能留下的开机启动关系。smail-admin 单元没有 [Install],不能再次 enable。
systemctl disable smail-admin >/dev/null 2>&1 || true
echo "Smail 已安装到 $runtime_dir,旧程序和服务文件备份在 $backup_dir。"
echo "配置、数据库和证书未覆盖;请使用 systemctl start smail 启动并检查运行状态。"
echo "smail-admin 仅允许按需执行 start/stop,不支持开机自启动。"
echo "主服务默认内存高水位 384 MiB、硬上限 512 MiB;不是容量承诺,请先核对同机资源预算。"
echo "旧环境文件不会自动补写 GOMEMLIMIT;启动后请按《生产资源部署说明》执行只读资源预检。"