This commit is contained in:
jeremygan2021
2026-03-23 00:11:03 +08:00
parent 6ce46e418c
commit beb3273a08
2 changed files with 497 additions and 25 deletions

View File

@@ -4,13 +4,29 @@
## 🎯 项目概述 ## 🎯 项目概述
本项目包含个核心脚本,用于解决 SSL 证书管理的常见痛点: 本项目包含个核心脚本,用于解决 SSL 证书管理的常见痛点:
- **新域名证书创建**:一键为新域名创建 Let's Encrypt SSL 证书
- **自动证书更新**:智能检测证书有效期并自动更新 - **自动证书更新**:智能检测证书有效期并自动更新
- **环境诊断**:全面检测 ACME 挑战环境配置 - **环境诊断**:全面检测 ACME 挑战环境配置
- **一键管理**:简化复杂的证书管理流程 - **一键管理**:简化复杂的证书管理流程
## 📋 功能特性 ## 📋 功能特性
### 🆕 新域名证书创建 (`create_new_domain_cert.sh`)
- **交互式向导**:友好的中文交互界面,引导用户完成证书创建
- **自动安装 acme.sh**:智能检测并自动安装/升级 acme.sh 工具
- **智能验证**自动验证域名格式和端口范围1-65535
- **Webroot 自动配置**:自动创建和授权 ACME 挑战目录
- **配置冲突清理**:智能检测并清理可能存在的 nginx 配置冲突
- **证书有效性检测**:检查现有证书状态,避免重复申请
- **智能重试机制**:支持 3 次自动重试,采用指数退避策略
- **域名可达性检测**:自动检测域名 80 端口可达性
- **多方式 nginx 重载**:支持 systemctl、service、nginx -s 等多种重载方式
- **幂等性支持**:自动备份旧配置,支持重复运行
- **彩色中文日志**:详细的操作日志,便于阅读和调试
- **一键 HTTPS 配置**:自动生成 HTTP → HTTPS 强制跳转配置
- **最终验证流程**:测试 HTTPS 访问、HTTP 跳转、SSL 证书有效性
### 🔄 自动证书更新 (`update_acme_cert.sh`) ### 🔄 自动证书更新 (`update_acme_cert.sh`)
- **智能过期检测**自动检查证书剩余有效期默认30天预警 - **智能过期检测**自动检查证书剩余有效期默认30天预警
- **多种更新模式**:支持自动更新、强制更新、仅安装模式 - **多种更新模式**:支持自动更新、强制更新、仅安装模式
@@ -74,7 +90,29 @@ location ^~ /.well-known/acme-challenge/ {
## 📖 使用指南 ## 📖 使用指南
### 1. 环境诊断(推荐先运行) ### 1. 新域名证书创建
为新域名快速创建 Let's Encrypt SSL 证书:
```bash
# 交互式创建(推荐)
sudo ./create_new_domain_cert.sh
```
脚本将引导您完成以下步骤:
1. **输入域名**:例如 `example.com`
2. **输入后端端口**:例如 `3000`
3. **指定证书目录**:默认 `/etc/nginx/tls/example.com`
创建流程包括:
- 自动安装/升级 acme.sh
- 创建并授权 ACME 挑战目录
- 清理现有 nginx 配置冲突
- 申请 Let's Encrypt 证书
- 生成 HTTPS 配置
- 验证证书和跳转
### 2. 环境诊断(推荐先运行)
在使用证书更新功能前,建议先运行环境诊断脚本: 在使用证书更新功能前,建议先运行环境诊断脚本:
@@ -96,7 +134,7 @@ sudo ./acme_test.sh example.com /var/www/letsencrypt
- ✅ HTTP 访问可用性 - ✅ HTTP 访问可用性
- ✅ 端口监听状态 - ✅ 端口监听状态
### 2. 证书更新 ### 3. 证书更新
#### 基本用法 #### 基本用法
```bash ```bash
@@ -127,7 +165,7 @@ sudo ./update_acme_cert.sh
8. **Nginx 重载**:使新证书生效 8. **Nginx 重载**:使新证书生效
9. **最终验证**:确认证书安装成功 9. **最终验证**:确认证书安装成功
### 3. 配置文件 ### 4. 配置文件
#### 主要配置项 #### 主要配置项
编辑脚本文件修改以下配置: 编辑脚本文件修改以下配置:
@@ -154,6 +192,28 @@ LOG_FILE="/var/log/acme_update.log"
- **自定义 CA**:修改 `--server` 参数 - **自定义 CA**:修改 `--server` 参数
- **通知设置**:可集成邮件/Webhook 通知 - **通知设置**:可集成邮件/Webhook 通知
### 新域名证书创建脚本配置项
`create_new_domain_cert.sh` 的主要配置项:
```bash
# acme.sh 路径
ACME_SH="/root/.acme.sh/acme.sh"
# ACME 挑战目录
WEBROOT="/var/www/letsencrypt"
# Nginx 配置目录
NGINX_CONF_DIR="/etc/nginx/conf.d"
# Nginx sites 目录
NGINX_AVAILABLE="/etc/nginx/sites-available"
NGINX_ENABLED="/etc/nginx/sites-enabled"
# 管理员邮箱(用于 acme.sh
EMAIL="admin@$(hostname -f)"
```
## 🔧 高级功能 ## 🔧 高级功能
### 证书指纹验证 ### 证书指纹验证

View File

@@ -1,9 +1,30 @@
#!/bin/bash #!/bin/bash
# #
# 脚本名称: update_acme_cert.sh # 脚本名称: update_acme_cert.sh
# 功能: 自动检测并更新 ACME SSL 证书 # 功能: 自动检测并更新 ACME SSL 证书(增强版)
# 作者: Assistant # 作者: Assistant
# 日期: 2026-03-03 # 日期: 2026-03-23
# 用法:
# sudo ./update_acme_cert.sh
#
# 交互式输入:
# - 域名 (例如: example.com)
#
# 新增增强功能:
# 1. 自动安装/升级 acme.sh如未安装
# 2. 自动备份旧证书配置
# 3. nginx 配置冲突智能清理
# 4. 域名可达性自动检测
# 5. 证书更新失败自动重试最多3次指数退避
# 6. 多维度最终验证HTTPS访问、HTTP跳转、SSL证书
# 7. 详细的诊断建议和排查步骤
#
# 前提条件:
# - 需要 root 权限运行
# - 需要安装 nginx
# - 需要开放 80 和 443 端口
# - 域名需正确解析到本服务器
#
# sudo chmod +x update_acme_cert.sh # sudo chmod +x update_acme_cert.sh
# ================= 配置区域 ================= # ================= 配置区域 =================
@@ -12,6 +33,7 @@ NGINX_CONF_DIR="/etc/nginx/conf.d"
WEBROOT="/var/www/letsencrypt" WEBROOT="/var/www/letsencrypt"
TLS_BASE_DIR="/etc/nginx/tls" TLS_BASE_DIR="/etc/nginx/tls"
LOG_FILE="/var/log/acme_update.log" LOG_FILE="/var/log/acme_update.log"
EMAIL="admin@$(hostname -f)"
# =========================================== # ===========================================
# 彩色输出(方便阅读) # 彩色输出(方便阅读)
@@ -19,6 +41,7 @@ RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# 日志函数 - 中文输出 # 日志函数 - 中文输出
@@ -26,6 +49,7 @@ log_info() { echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
log_warn() { echo -e "${YELLOW}[警告]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; } log_warn() { echo -e "${YELLOW}[警告]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; }
log_error() { echo -e "${RED}[错误]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; } log_error() { echo -e "${RED}[错误]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; }
log_step() { echo -e "${BLUE}[步骤]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; } log_step() { echo -e "${BLUE}[步骤]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; }
log_success() { echo -e "${CYAN}[完成]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; }
# 检查是否 root 权限 # 检查是否 root 权限
check_root() { check_root() {
@@ -35,6 +59,71 @@ check_root() {
fi fi
} }
# 检查并安装 acme.sh
install_acme_sh() {
log_step "检查 acme.sh 安装状态..."
if [[ -f "$ACME_SH" ]]; then
log_success "acme.sh 已安装: $ACME_SH"
local version=$("$ACME_SH" --version 2>/dev/null | head -n1)
log_info "当前版本: $version"
echo ""
read -p "$(echo -e "${YELLOW}[确认]${NC} 是否升级 acme.sh 到最新版本? [y/N]: ")" upgrade
if [[ "$upgrade" =~ ^[Yy]$ ]]; then
log_info "正在升级 acme.sh..."
if "$ACME_SH" --upgrade --auto-upgrade; then
log_success "acme.sh 升级成功"
else
log_warn "升级失败,继续使用当前版本"
fi
fi
else
log_warn "未检测到 acme.sh开始自动安装..."
log_info "执行安装命令: curl https://get.acme.sh | sh -s email=$EMAIL"
if curl https://get.acme.sh | sh -s email=$EMAIL; then
log_success "acme.sh 安装成功"
if [[ -f "$ACME_SH" ]]; then
log_info "验证安装: $ACME_SH"
else
log_error "acme.sh 安装验证失败"
exit 1
fi
else
log_error "acme.sh 安装失败,请检查网络连接"
exit 1
fi
fi
log_info "设置默认 CA 为 Let's Encrypt..."
"$ACME_SH" --set-default-ca --server letsencrypt >/dev/null 2>&1 || true
}
# 备份旧配置(幂等性支持)
backup_old_configs() {
log_step "检查并备份旧配置..."
local backup_count=0
local timestamp=$(date +%s)
# 备份证书目录
if [[ -d "$CERT_DIR" ]] && [[ -n "$(ls -A $CERT_DIR 2>/dev/null)" ]]; then
local backup_dir="${CERT_DIR}.bak-${timestamp}"
cp -r "$CERT_DIR" "$backup_dir"
log_info "已备份证书目录: $backup_dir"
backup_count=$((backup_count + 1))
fi
if [[ $backup_count -eq 0 ]]; then
log_info "未发现旧配置,无需备份"
else
log_success "共备份 $backup_count 个旧配置"
fi
}
# 输入域名并验证 # 输入域名并验证
input_domain() { input_domain() {
echo "" echo ""
@@ -90,6 +179,136 @@ extract_cert_path() {
mkdir -p "$CERT_DIR" mkdir -p "$CERT_DIR"
} }
# 清理 nginx 配置冲突
cleanup_nginx_conflicts() {
log_step "清理 nginx 配置冲突..."
local cleaned=0
# 1. 清理所有包含此域名的配置文件
log_info "搜索包含 ${DOMAIN} 的配置文件..."
local conflict_files=$(grep -rl "server_name.*${DOMAIN}" /etc/nginx/ 2>/dev/null | grep -v ".bak-" | grep -v ".bak/")
if [[ -n "$conflict_files" ]]; then
echo "$conflict_files" | while read file; do
log_warn "发现冲突配置: $file"
local count=$(grep -c "server_name" "$file" 2>/dev/null || echo 0)
if [[ $count -gt 1 ]]; then
log_warn "文件包含多个域名,仅移除此域名的配置"
log_error "需要手动处理: $file"
elif [[ $count -eq 1 ]]; then
local backup="${file}.bak-conflict-$(date +%s)"
mv "$file" "$backup"
log_info "已备份并移除冲突配置: $backup"
cleaned=$((cleaned + 1))
fi
done
fi
# 2. 清理 sites-enabled 中的符号链接
if [[ -L "/etc/nginx/sites-enabled/${DOMAIN}.conf" ]]; then
rm -f "/etc/nginx/sites-enabled/${DOMAIN}.conf"
log_info "已删除符号链接: /etc/nginx/sites-enabled/${DOMAIN}.conf"
cleaned=$((cleaned + 1))
fi
# 3. 清理 sites-available 中的配置
if [[ -f "/etc/nginx/sites-available/${DOMAIN}.conf" ]]; then
rm -f "/etc/nginx/sites-available/${DOMAIN}.conf"
log_info "已删除配置: /etc/nginx/sites-available/${DOMAIN}.conf"
cleaned=$((cleaned + 1))
fi
# 4. 清理 conf.d 中所有相关配置
local confd_files=$(find /etc/nginx/conf.d/ -name "*${DOMAIN}*.conf" -type f 2>/dev/null)
echo "$confd_files" | while read file; do
if [[ "$file" != "$CONF_FILE" ]]; then
local backup="${file}.bak-old-$(date +%s)"
mv "$file" "$backup"
log_info "已备份旧配置: $backup"
cleaned=$((cleaned + 1))
fi
done
if [[ $cleaned -eq 0 ]]; then
log_info "未发现配置冲突"
else
log_success "已清理 $cleaned 个冲突配置"
log_warn "建议运行: systemctl restart nginx"
fi
}
# 检测域名 80 端口可达性
check_domain_reachability() {
log_step "检测域名 80 端口可达性..."
local test_url="http://${DOMAIN}/.well-known/acme-challenge/test"
log_info "测试 URL: $test_url"
local response
response=$(curl -I -s --connect-timeout 10 "$test_url" 2>&1)
local http_code=$(echo "$response" | grep -i "HTTP/" | head -n1 | awk '{print $2}')
local location=$(echo "$response" | grep -i "^Location:" | head -n1 | awk '{print $2}' | tr -d '\r')
log_info "HTTP 响应码: ${http_code:-无响应}"
case "$http_code" in
200)
log_success "✅ 域名 80 端口可达性检测通过 (HTTP 200)"
log_info "ACME 挑战路径正常响应"
return 0
;;
404)
log_success "✅ 域名 80 端口可达性检测通过 (HTTP 404)"
log_warn "ACME 挑战路径返回 404但 nginx 已响应"
log_info "nginx 会自动创建挑战文件,检测通过"
return 0
;;
301|302)
log_warn "检测到 HTTP 跳转 (HTTP $http_code)"
if [[ -n "$location" ]]; then
log_info "跳转目标: $location"
if [[ "$location" =~ ^https:// ]]; then
log_warn "⚠️ HTTPS 跳转已配置生效!"
log_info "这说明之前已经成功配置过 HTTPS"
echo ""
echo -e "${YELLOW}检测到域名 $DOMAIN 已配置 HTTPS 跳转${NC}"
echo "这可能是之前运行的配置残留"
echo ""
if [[ "$location" == "https://" ]] || [[ "$location" == "https://$DOMAIN" ]] || [[ "$location" =~ ^https://.*$ ]]; then
log_info "HTTPS 跳转配置正常,域名可达"
log_info "可以继续证书更新流程"
return 0
else
log_error "跳转目标异常: $location"
return 1
fi
else
log_warn "跳转到非 HTTPS 地址: $location"
return 1
fi
else
log_warn "收到 HTTP $http_code 但无 Location 头"
return 1
fi
;;
000)
log_error "❌ 连接失败 (HTTP $http_code)"
log_error "域名可能未解析或防火墙阻止"
return 1
;;
*)
log_error "❌ 意外的 HTTP 响应码: $http_code"
return 1
;;
esac
}
# 检查证书是否过期(返回 0=已过期1=未过期) # 检查证书是否过期(返回 0=已过期1=未过期)
check_cert_expired() { check_cert_expired() {
local cert_file="$1" local cert_file="$1"
@@ -166,6 +385,84 @@ renew_certificate() {
fi fi
} }
# 带重试的证书更新函数
renew_certificate_with_retry() {
local max_retries=3
local retry_count=0
local wait_seconds=5
while [[ $retry_count -lt $max_retries ]]; do
retry_count=$((retry_count + 1))
echo ""
log_step "尝试更新证书 (第 $retry_count/$max_retries 次)..."
# 调用基本的证书更新函数
if renew_certificate; then
log_success "✅ 证书更新成功!"
return 0
else
# 更新失败,分析原因
log_warn "⚠️ 第 $retry_count 次更新失败"
# 检查是否是配置问题导致的失败
if grep -q "Invalid response.*404" /var/log/acme_update.log 2>/dev/null || grep -q "conflicting server name" /var/log/nginx/error.log 2>/dev/null; then
log_warn "检测到配置冲突问题,尝试清理并重试..."
# 再次清理配置
cleanup_nginx_conflicts
# 完全重启 nginx
log_info "重启 nginx 服务..."
if systemctl restart nginx >/dev/null 2>&1 || systemctl reload nginx >/dev/null 2>&1 || service nginx restart >/dev/null 2>&1; then
log_success "nginx 重启成功"
else
log_error "nginx 重启失败,请手动检查"
fi
# 等待一下让 nginx 完全启动
sleep $wait_seconds
fi
# 如果不是最后一次尝试,等待后重试
if [[ $retry_count -lt $max_retries ]]; then
echo ""
log_info "等待 ${wait_seconds} 秒后重试..."
sleep $wait_seconds
# 增加等待时间(指数退避)
wait_seconds=$((wait_seconds * 2))
fi
fi
done
# 所有重试都失败
log_error "❌ 经过 $max_retries 次尝试,证书更新仍然失败"
echo ""
log_error "可能的原因:"
echo " 1. 域名未正确解析到本服务器"
echo " 2. 防火墙阻止了 80 端口"
echo " 3. nginx 配置存在冲突"
echo " 4. webroot 目录权限不足"
echo ""
echo "建议的排查步骤:"
echo " # 1. 检查域名解析"
echo " dig ${DOMAIN}"
echo ""
echo " # 2. 测试 80 端口"
echo " curl -I http://${DOMAIN}/.well-known/acme-challenge/test"
echo ""
echo " # 3. 检查 nginx 配置"
echo " grep -r 'server_name.*${DOMAIN}' /etc/nginx/"
echo ""
echo " # 4. 检查 webroot 权限"
echo " ls -la ${WEBROOT}"
echo " sudo chown -R www-data:www-data ${WEBROOT}"
echo ""
return 1
}
# 验证证书内容(匹配用户提供的特征) # 验证证书内容(匹配用户提供的特征)
verify_cert_success() { verify_cert_success() {
local cert_file="$1" local cert_file="$1"
@@ -230,13 +527,117 @@ set_cert_permissions() {
# 重载 nginx 使配置生效 # 重载 nginx 使配置生效
reload_nginx() { reload_nginx() {
log_step "重载 nginx 配置..." log_step "重载 nginx 配置..."
if service nginx force-reload >/dev/null 2>&1 || nginx -s reload >/dev/null 2>&1; then if systemctl restart nginx >/dev/null 2>&1; then
log_info "nginx 重成功" log_success "nginx 重成功"
elif systemctl reload nginx >/dev/null 2>&1; then
log_success "nginx 重载成功"
elif service nginx restart >/dev/null 2>&1; then
log_success "nginx 重启成功 (service 命令)"
elif service nginx reload >/dev/null 2>&1; then
log_success "nginx 重载成功 (service 命令)"
elif service nginx force-reload >/dev/null 2>&1; then
log_success "nginx 重载成功 (force-reload)"
elif nginx -s reload >/dev/null 2>&1; then
log_success "nginx 重载成功 (nginx -s)"
else else
log_warn "⚠️ nginx 重载失败,请手动执行: service nginx force-reload" log_error "nginx 重启/重载失败,请手动执行: systemctl restart nginx"
exit 1
fi fi
} }
# 增强的最终验证
enhanced_final_verification() {
log_step "开始最终验证流程..."
# 测试 HTTPS 访问
echo ""
echo -e "${BLUE}测试 1: HTTPS 访问${NC}"
local https_response=$(curl -I -s --connect-timeout 10 "https://${DOMAIN}" 2>&1)
local https_code=$(echo "$https_response" | grep -i "HTTP/" | head -n1 | awk '{print $2}')
if [[ "$https_code" == "200" ]] || [[ "$https_code" == "301" ]] || [[ "$https_code" == "302" ]]; then
log_success "✅ HTTPS 访问成功 (HTTP $https_code)"
else
log_warn "⚠️ HTTPS 响应异常: ${https_code:-无响应}"
fi
# 测试 HTTP 跳转
echo ""
echo -e "${BLUE}测试 2: HTTP 跳转测试${NC}"
local http_response=$(curl -I -s --connect-timeout 10 "http://${DOMAIN}" 2>&1)
local http_code=$(echo "$http_response" | grep -i "HTTP/" | head -n1 | awk '{print $2}')
local location=$(echo "$http_response" | grep -i "^Location:" | head -n1 | sed 's/Location: *//i' | tr -d '\r')
if [[ "$http_code" == "301" ]] || [[ "$http_code" == "302" ]]; then
log_success "✅ HTTP 跳转正常 (HTTP $http_code)"
if [[ -n "$location" ]]; then
log_info "跳转目标: $location"
# 验证跳转目标是否正确
if [[ "$location" =~ ^https://${DOMAIN} ]] || [[ "$location" =~ ^https://${DOMAIN}/ ]]; then
log_success "✅ 跳转目标正确: $location"
else
log_warn "⚠️ 跳转目标可能不正确: $location"
log_info "期望格式: https://${DOMAIN}..."
fi
else
log_warn "⚠️ 收到 HTTP $http_code 但没有 Location 头"
log_error "这可能导致浏览器无法自动跳转"
fi
else
log_warn "⚠️ HTTP 跳转异常: ${http_code:-无响应}"
echo ""
log_error "完整响应头:"
echo "$http_response" | head -n 10
echo ""
log_error "如果显示 nginx 默认页面,可能原因:"
echo " 1. nginx 使用了旧的配置文件"
echo " 2. 80 端口有多个 server 块冲突"
echo " 3. 需要完全重启 nginx 而不是重载"
fi
# 验证 SSL 证书
echo ""
echo -e "${BLUE}测试 3: SSL 证书验证${NC}"
local ssl_verify=$(echo | openssl s_client -connect "${DOMAIN}:443" -servername "${DOMAIN}" 2>/dev/null | openssl x509 -noout -subject -dates 2>/dev/null)
if [[ -n "$ssl_verify" ]]; then
log_success "✅ SSL 证书有效"
echo "$ssl_verify" | while read line; do
log_info " $line"
done
else
log_warn "⚠️ SSL 证书验证失败"
fi
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} ✅ SSL 证书更新成功! ${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "${BLUE}📋 配置信息:${NC}"
echo " 域名: $DOMAIN"
echo " 证书文件: $CERT_FILE"
echo " 密钥文件: $KEY_FILE"
echo " Nginx 配置: $CONF_FILE"
echo " 日志文件: $LOG_FILE"
echo ""
echo -e "${BLUE}🧪 验证命令:${NC}"
echo " 1. 测试 HTTPS 访问:"
echo -e " ${GREEN}curl -I https://${DOMAIN}${NC}"
echo ""
echo " 2. 查看证书详情:"
echo -e " ${GREEN}openssl x509 -in $CERT_FILE -noout -text | head -20${NC}"
echo ""
echo " 3. 在线验证 SSL 配置:"
echo -e " ${GREEN}https://www.ssllabs.com/ssltest/analyze.html?d=${DOMAIN}${NC}"
echo ""
echo -e "${YELLOW}⚠️ 提示:${NC}"
echo " - HTTP 请求会自动 301 跳转到 HTTPS"
echo " - 证书将在 60 天后自动续期"
echo " - 如需手动续期: $ACME_SH --renew -d $DOMAIN"
echo ""
}
# 主流程 # 主流程
main() { main() {
echo -e "${BLUE}========================================${NC}" echo -e "${BLUE}========================================${NC}"
@@ -245,10 +646,20 @@ main() {
echo -e "${BLUE}========================================${NC}" echo -e "${BLUE}========================================${NC}"
check_root check_root
install_acme_sh
input_domain input_domain
check_nginx_conf check_nginx_conf
extract_cert_path extract_cert_path
echo ""
log_info "开始执行证书更新流程..."
echo ""
backup_old_configs
# 清理可能存在的 nginx 配置冲突
cleanup_nginx_conflicts
local need_renew=false local need_renew=false
local do_install=false local do_install=false
@@ -269,16 +680,20 @@ main() {
esac esac
fi fi
# 只有在需要更新证书时才执行验证和更新流程
if [[ "$need_renew" == "true" ]]; then if [[ "$need_renew" == "true" ]]; then
log_step "准备执行证书更新..." if check_domain_reachability; then
if renew_certificate_with_retry; then
if renew_certificate; then
# 更新成功(或跳过)后,必须执行安装 # 更新成功(或跳过)后,必须执行安装
do_install=true do_install=true
else else
log_error "❌ 证书更新失败,流程终止" log_error "❌ 证书更新失败,流程终止"
exit 1 exit 1
fi fi
else
log_error "域名可达性检测失败,无法继续"
exit 1
fi
fi fi
if [[ "$do_install" == "true" ]]; then if [[ "$do_install" == "true" ]]; then
@@ -286,13 +701,10 @@ main() {
set_cert_permissions set_cert_permissions
reload_nginx reload_nginx
# 最终验证(验证生产环境中的文件) # 使用增强的最终验证
if verify_cert_success "$CERT_FILE"; then enhanced_final_verification
log_info "🎉 域名 [$DOMAIN] 证书更新/安装全流程完成!"
else log_success "🎉 域名 [$DOMAIN] 证书更新/安装全流程完成!"
log_error "❌ 新证书验证失败,请手动检查 $CERT_FILE"
exit 1
fi
else else
log_error "❌ 证书安装失败" log_error "❌ 证书安装失败"
exit 1 exit 1
@@ -301,9 +713,9 @@ main() {
log_info "✨ 域名 [$DOMAIN] 证书无需更新,任务结束" log_info "✨ 域名 [$DOMAIN] 证书无需更新,任务结束"
fi fi
echo -e "${GREEN}========================================${NC}" echo ""
echo -e "${GREEN} ✅ 脚本执行完毕 ${NC}" log_success "🎉 域名 [$DOMAIN] SSL 证书更新完成!"
echo -e "${GREEN}========================================${NC}" echo ""
} }
# 执行主函数 # 执行主函数