fix: prompt before modifying existing installs

This commit is contained in:
zxyszx
2026-08-03 23:09:59 +08:00
parent ccd5c4efd5
commit 800d482c77
3 changed files with 75 additions and 1 deletions
+4
View File
@@ -35,6 +35,10 @@ curl -fsSL https://raw.githubusercontent.com/zxyszx/NewSzxcn-Email/main/install.
bash <(curl -fsSL https://raw.githubusercontent.com/zxyszx/NewSzxcn-Email/main/install.sh)
```
空白服务器会进入防火墙、邮件域名、管理员账号和 Web 部署方式的引导。检测到
`/opt/newszxcn-email/.env` 时,脚本会先询问是更新现有邮局、修复现有安装还是退出;
不会再直接跳过引导并重启服务。更新会先备份数据库,并在启动失败时自动回滚。
脚本会自动完成:
- 安装或检查 Docker Engine 与 Docker Compose v2
+54 -1
View File
@@ -21,7 +21,7 @@ NewSzxcn Email 管理命令
用法:newszxcn-email <command>
install 首次安装或修复部署
install 首次安装;检测到已有安装时显示操作菜单
update 备份数据库并更新到最新版
status 查看容器与健康状态
logs 持续查看运行日志
@@ -163,6 +163,21 @@ 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"
fi
prompt_text '请选择操作 [1]:\n1. 更新现有邮局(推荐,自动备份并支持回滚)\n2. 修复现有安装(保留配置和数据)\n3. 退出,不做任何修改\n'
if [[ -z "${LANQIN_EXISTING_ACTION:-}" ]] && ! has_tty; then
fail "非交互环境不能选择已有安装操作;更新请执行 newszxcn-email update。"
fi
action="$(prompt_choice LANQIN_EXISTING_ACTION "请选择 [1]: " "1")"
printf '%s' "${action}"
}
has_tty() {
[[ -e /dev/tty ]] && (: </dev/tty) 2>/dev/null
}
@@ -562,7 +577,45 @@ remember_current_image() {
printf '%s\n' "${rollback_tag}" > "${ROLLBACK_FILE}"
}
do_repair_install() {
refresh_assets
ensure_update_token
configure_runtime_bindings
ensure_docker
backup_database
remember_current_image
configure_firewall
prepare_directories
log "正在拉取并修复 NewSzxcn Email 服务..."
compose pull
log "正在启动服务..."
if ! compose up -d --remove-orphans; then
warn "修复后容器启动失败,正在自动回滚。"
do_rollback
fail "修复失败,已回滚到原镜像。"
fi
if ! wait_for_health 90; then
warn "修复后健康检查失败,正在自动回滚。"
do_rollback
fail "修复失败,已回滚到原镜像。"
fi
configure_web_mode
success "安装完成:$(env_value LANQIN_PUBLIC_BASE_URL)"
warn "下一步请配置 MX、SPF、DKIM、DMARC,并确认 25/465/587/993/995 端口可访问。"
}
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 "已退出,现有邮局未作修改。" ;;
esac
return
fi
refresh_assets
configure_first_install
ensure_update_token
+17
View File
@@ -109,6 +109,22 @@ test_legacy_configuration_is_preserved() {
assert_eq "127.0.0.1:9090" "$(env_value LANQIN_HTTP_BIND)" "legacy HTTP bind"
}
test_existing_install_action() {
local temp_dir
temp_dir="$(mktemp -d)"
cp "${ROOT_DIR}/deploy/.env.example" "${temp_dir}/.env"
export INSTALL_DIR="${temp_dir}"
set_env LANQIN_PUBLIC_BASE_URL "https://mail.example.com"
export LANQIN_EXISTING_ACTION=1
assert_eq "1" "$(prompt_existing_install_action)" "existing install update action"
export LANQIN_EXISTING_ACTION=2
assert_eq "2" "$(prompt_existing_install_action)" "existing install repair action"
export LANQIN_EXISTING_ACTION=3
assert_eq "3" "$(prompt_existing_install_action)" "existing install exit action"
unset LANQIN_EXISTING_ACTION
}
test_hostname_validation
test_password_validation
test_install_configuration 1 1 "127.0.0.1:8088" "https://mail.example.com" "false"
@@ -117,5 +133,6 @@ test_install_configuration 3 3 "80" "http://mail.example.com" "true"
test_nginx_configuration
test_compose_configuration
test_legacy_configuration_is_preserved
test_existing_install_action
printf 'install.sh tests passed\n'