feat: add unified installer management menu

This commit is contained in:
zxyszx
2026-08-03 23:29:02 +08:00
parent b55c298ef4
commit 697ed236cc
3 changed files with 84 additions and 43 deletions
+71 -22
View File
@@ -4,7 +4,7 @@ set -Eeuo pipefail
REPOSITORY="zxyszx/NewSzxcn-Email"
RAW_BASE="https://raw.githubusercontent.com/${REPOSITORY}/main"
INSTALL_DIR="${LANQIN_INSTALL_DIR:-/opt/newszxcn-email}"
COMMAND="${1:-install}"
COMMAND="${1:-menu}"
ROLLBACK_FILE="${INSTALL_DIR}/.rollback-image"
NGINX_CONFIG="/etc/nginx/conf.d/newszxcn-email.conf"
ACME_WEBROOT="/var/www/newszxcn-acme"
@@ -21,7 +21,8 @@ NewSzxcn Email 管理命令
用法:newszxcn-email <command>
install 首次安装;检测到已有安装时显示操作菜单
menu 显示安装与运维菜单
install 首次安装;已有安装会先完整备份再重新安装
update 备份数据库并更新到最新版
status 查看容器与健康状态
logs 持续查看运行日志
@@ -163,19 +164,24 @@ prompt_choice() {
done
}
prompt_existing_install_action() {
local public_url action
public_url="$(env_value LANQIN_PUBLIC_BASE_URL || true)"
prompt_text "\n[发现] 检测到已有 NewSzxcn Email 安装:${INSTALL_DIR}\n"
if [[ -n "${public_url}" ]]; then
prompt_text "[发现] 当前访问地址:${public_url}\n"
prompt_menu_choice() {
local default_value="$1" value="${LANQIN_MENU_ACTION:-}"
if [[ -z "${value}" ]] && ! has_tty; then
fail "非交互环境请直接使用 install、update、status 等子命令。"
fi
prompt_text '请选择操作 [1]:\n1. 更新现有邮局(推荐,自动备份并支持回滚)\n2. 修复现有安装(保留配置和数据)\n3. 退出,不做任何修改\n4. 备份现有安装并全新安装\n'
if [[ -z "${LANQIN_EXISTING_ACTION:-}" ]] && ! has_tty; then
fail "非交互环境不能选择已有安装操作;更新请执行 newszxcn-email update。"
fi
action="$(prompt_choice LANQIN_EXISTING_ACTION "请选择 [1]: " "1" "4")"
printf '%s' "${action}"
while true; do
if [[ -z "${value}" ]] && has_tty; then
read -r -p "请选择 [${default_value}]: " value </dev/tty
fi
value="${value:-${default_value}}"
if [[ "${value}" =~ ^[0-9]$ ]]; then
printf '%s' "${value}"
return
fi
prompt_text "[提示] 请输入 0 至 9。\n"
value=""
has_tty || fail "LANQIN_MENU_ACTION 必须设置为 0 至 9。"
done
}
has_tty() {
@@ -605,15 +611,8 @@ do_repair_install() {
}
do_install() {
local action
if [[ -f "${INSTALL_DIR}/.env" ]]; then
action="$(prompt_existing_install_action)"
case "${action}" in
1) do_update ;;
2) do_repair_install ;;
3) success "已退出,现有邮局未作修改。" ;;
4) do_backup_reinstall ;;
esac
do_backup_reinstall
return
fi
@@ -749,6 +748,55 @@ do_backup_reinstall() {
do_install
}
do_menu() {
local installed="false" default_choice="1" public_url="" choice
if [[ -f "${INSTALL_DIR}/.env" ]]; then
installed="true"
default_choice="2"
public_url="$(env_value LANQIN_PUBLIC_BASE_URL || true)"
fi
prompt_text '\n==================================================\n'
prompt_text ' NewSzxcn Email 一键安装与管理\n'
prompt_text '==================================================\n'
if [[ "${installed}" == "true" ]]; then
prompt_text " 状态:已安装\n 路径:${INSTALL_DIR}\n"
[[ -n "${public_url}" ]] && prompt_text " 地址:${public_url}\n"
else
prompt_text ' 状态:未安装\n'
fi
prompt_text '--------------------------------------------------\n'
prompt_text ' 1. 安装 / 重新安装(旧数据自动备份)\n'
prompt_text ' 2. 更新系统(数据库自动备份)\n'
prompt_text ' 3. 修复现有安装\n'
prompt_text ' 4. 查看运行状态\n'
prompt_text ' 5. 重启服务\n'
prompt_text ' 6. 查看实时日志\n'
prompt_text ' 7. 申请或续期 SSL 证书\n'
prompt_text ' 8. 回滚上个命令行版本\n'
prompt_text ' 9. 卸载服务(保留数据)\n'
prompt_text ' 0. 退出\n'
prompt_text '==================================================\n'
choice="$(prompt_menu_choice "${default_choice}")"
if [[ "${choice}" != "0" && "${choice}" != "1" && "${installed}" != "true" ]]; then
fail "尚未安装,请先选择 1。"
fi
case "${choice}" in
0) success "已退出,未作任何修改。" ;;
1) do_install ;;
2) do_update ;;
3) do_repair_install ;;
4) ensure_docker; do_status ;;
5) do_restart ;;
6) ensure_docker; compose logs -f --tail=200 lanqin-email updater ;;
7) do_certificate ;;
8) ensure_docker; do_rollback ;;
9) ensure_docker; do_uninstall ;;
esac
}
if [[ "${LANQIN_SOURCE_ONLY:-false}" == "true" ]]; then
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then
return 0
@@ -758,6 +806,7 @@ fi
case "${COMMAND}" in
help|-h|--help) usage ;;
menu) require_root; require_curl; do_menu ;;
install) require_root; require_curl; do_install ;;
update) require_root; require_curl; do_update ;;
status) require_root; require_curl; ensure_docker; do_status ;;