feat: add safe fresh reinstall option
This commit is contained in:
@@ -36,8 +36,9 @@ bash <(curl -fsSL https://raw.githubusercontent.com/zxyszx/NewSzxcn-Email/main/i
|
|||||||
```
|
```
|
||||||
|
|
||||||
空白服务器会进入防火墙、邮件域名、管理员账号和 Web 部署方式的引导。检测到
|
空白服务器会进入防火墙、邮件域名、管理员账号和 Web 部署方式的引导。检测到
|
||||||
`/opt/newszxcn-email/.env` 时,脚本会先询问是更新现有邮局、修复现有安装还是退出;
|
`/opt/newszxcn-email/.env` 时,脚本会先询问是更新现有邮局、修复现有安装、退出,
|
||||||
不会再直接跳过引导并重启服务。更新会先备份数据库,并在启动失败时自动回滚。
|
还是完整备份旧目录后全新安装;不会再直接跳过引导并重启服务。更新会先备份数据库,
|
||||||
|
并在启动失败时自动回滚。
|
||||||
|
|
||||||
脚本会自动完成:
|
脚本会自动完成:
|
||||||
|
|
||||||
|
|||||||
+32
-6
@@ -146,20 +146,20 @@ prompt_value() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prompt_choice() {
|
prompt_choice() {
|
||||||
local variable="$1" prompt="$2" default_value="$3" value
|
local variable="$1" prompt="$2" default_value="$3" max_value="${4:-3}" value
|
||||||
value="${!variable:-}"
|
value="${!variable:-}"
|
||||||
while true; do
|
while true; do
|
||||||
if [[ -z "${value}" ]] && has_tty; then
|
if [[ -z "${value}" ]] && has_tty; then
|
||||||
read -r -p "${prompt}" value </dev/tty
|
read -r -p "${prompt}" value </dev/tty
|
||||||
fi
|
fi
|
||||||
value="${value:-${default_value}}"
|
value="${value:-${default_value}}"
|
||||||
if [[ "${value}" =~ ^[123]$ ]]; then
|
if [[ "${value}" =~ ^[0-9]+$ ]] && (( value >= 1 && value <= max_value )); then
|
||||||
printf '%s' "${value}"
|
printf '%s' "${value}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
prompt_text "[提示] 请输入 1、2 或 3。\n"
|
prompt_text "[提示] 请输入 1 至 ${max_value}。\n"
|
||||||
value=""
|
value=""
|
||||||
has_tty || fail "${variable} 必须设置为 1、2 或 3。"
|
has_tty || fail "${variable} 必须设置为 1 至 ${max_value}。"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,11 +170,11 @@ prompt_existing_install_action() {
|
|||||||
if [[ -n "${public_url}" ]]; then
|
if [[ -n "${public_url}" ]]; then
|
||||||
prompt_text "[发现] 当前访问地址:${public_url}\n"
|
prompt_text "[发现] 当前访问地址:${public_url}\n"
|
||||||
fi
|
fi
|
||||||
prompt_text '请选择操作 [1]:\n1. 更新现有邮局(推荐,自动备份并支持回滚)\n2. 修复现有安装(保留配置和数据)\n3. 退出,不做任何修改\n'
|
prompt_text '请选择操作 [1]:\n1. 更新现有邮局(推荐,自动备份并支持回滚)\n2. 修复现有安装(保留配置和数据)\n3. 退出,不做任何修改\n4. 备份现有安装并全新安装\n'
|
||||||
if [[ -z "${LANQIN_EXISTING_ACTION:-}" ]] && ! has_tty; then
|
if [[ -z "${LANQIN_EXISTING_ACTION:-}" ]] && ! has_tty; then
|
||||||
fail "非交互环境不能选择已有安装操作;更新请执行 newszxcn-email update。"
|
fail "非交互环境不能选择已有安装操作;更新请执行 newszxcn-email update。"
|
||||||
fi
|
fi
|
||||||
action="$(prompt_choice LANQIN_EXISTING_ACTION "请选择 [1]: " "1")"
|
action="$(prompt_choice LANQIN_EXISTING_ACTION "请选择 [1]: " "1" "4")"
|
||||||
printf '%s' "${action}"
|
printf '%s' "${action}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,6 +612,7 @@ do_install() {
|
|||||||
1) do_update ;;
|
1) do_update ;;
|
||||||
2) do_repair_install ;;
|
2) do_repair_install ;;
|
||||||
3) success "已退出,现有邮局未作修改。" ;;
|
3) success "已退出,现有邮局未作修改。" ;;
|
||||||
|
4) do_backup_reinstall ;;
|
||||||
esac
|
esac
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
@@ -723,6 +724,31 @@ do_uninstall() {
|
|||||||
success "容器和自动生成的 Nginx 配置已移除,${INSTALL_DIR} 中的邮件、证书、配置和数据库仍然保留。"
|
success "容器和自动生成的 Nginx 配置已移除,${INSTALL_DIR} 中的邮件、证书、配置和数据库仍然保留。"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do_backup_reinstall() {
|
||||||
|
local backup_dir
|
||||||
|
backup_dir="${INSTALL_DIR}.backup-$(date -u +%Y%m%dT%H%M%SZ)"
|
||||||
|
|
||||||
|
if [[ -f "${INSTALL_DIR}/docker-compose.yml" ]] && command -v docker >/dev/null 2>&1; then
|
||||||
|
ensure_docker
|
||||||
|
compose down --remove-orphans
|
||||||
|
fi
|
||||||
|
if [[ -f "${NGINX_CONFIG}" ]]; then
|
||||||
|
rm -f "${NGINX_CONFIG}"
|
||||||
|
if command -v nginx >/dev/null 2>&1 && nginx -t >/dev/null 2>&1; then
|
||||||
|
if command -v systemctl >/dev/null 2>&1; then
|
||||||
|
systemctl reload nginx
|
||||||
|
else
|
||||||
|
nginx -s reload
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv "${INSTALL_DIR}" "${backup_dir}"
|
||||||
|
success "旧安装已完整备份到 ${backup_dir}。"
|
||||||
|
log "现在开始全新安装。"
|
||||||
|
do_install
|
||||||
|
}
|
||||||
|
|
||||||
if [[ "${LANQIN_SOURCE_ONLY:-false}" == "true" ]]; then
|
if [[ "${LANQIN_SOURCE_ONLY:-false}" == "true" ]]; then
|
||||||
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then
|
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -122,9 +122,29 @@ test_existing_install_action() {
|
|||||||
assert_eq "2" "$(prompt_existing_install_action)" "existing install repair action"
|
assert_eq "2" "$(prompt_existing_install_action)" "existing install repair action"
|
||||||
export LANQIN_EXISTING_ACTION=3
|
export LANQIN_EXISTING_ACTION=3
|
||||||
assert_eq "3" "$(prompt_existing_install_action)" "existing install exit action"
|
assert_eq "3" "$(prompt_existing_install_action)" "existing install exit action"
|
||||||
|
export LANQIN_EXISTING_ACTION=4
|
||||||
|
assert_eq "4" "$(prompt_existing_install_action)" "existing install fresh action"
|
||||||
unset LANQIN_EXISTING_ACTION
|
unset LANQIN_EXISTING_ACTION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_backup_reinstall_preserves_existing_directory() (
|
||||||
|
local temp_dir backup_dir
|
||||||
|
temp_dir="$(mktemp -d)"
|
||||||
|
INSTALL_DIR="${temp_dir}/newszxcn-email"
|
||||||
|
NGINX_CONFIG="${temp_dir}/newszxcn-email.conf"
|
||||||
|
mkdir -p "${INSTALL_DIR}"
|
||||||
|
printf 'existing-data\n' > "${INSTALL_DIR}/marker"
|
||||||
|
|
||||||
|
do_install() {
|
||||||
|
[[ ! -e "${INSTALL_DIR}" ]] || fail_test "fresh install started before old directory was moved"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_backup_reinstall
|
||||||
|
backup_dir="$(find "${temp_dir}" -maxdepth 1 -type d -name 'newszxcn-email.backup-*' -print -quit)"
|
||||||
|
[[ -n "${backup_dir}" ]] || fail_test "existing install backup directory missing"
|
||||||
|
grep -Fq 'existing-data' "${backup_dir}/marker" || fail_test "existing install data was not preserved"
|
||||||
|
)
|
||||||
|
|
||||||
test_hostname_validation
|
test_hostname_validation
|
||||||
test_password_validation
|
test_password_validation
|
||||||
test_install_configuration 1 1 "127.0.0.1:8088" "https://mail.example.com" "false"
|
test_install_configuration 1 1 "127.0.0.1:8088" "https://mail.example.com" "false"
|
||||||
@@ -134,5 +154,6 @@ test_nginx_configuration
|
|||||||
test_compose_configuration
|
test_compose_configuration
|
||||||
test_legacy_configuration_is_preserved
|
test_legacy_configuration_is_preserved
|
||||||
test_existing_install_action
|
test_existing_install_action
|
||||||
|
test_backup_reinstall_preserves_existing_directory
|
||||||
|
|
||||||
printf 'install.sh tests passed\n'
|
printf 'install.sh tests passed\n'
|
||||||
|
|||||||
Reference in New Issue
Block a user