嗯,优化了显示顺序与部署逻辑的全新Deploy.sh 3.0

This commit is contained in:
2026-08-05 23:43:05 +08:00
parent 6038f81248
commit c03c8cf9ce
+27 -90
View File
@@ -34,18 +34,18 @@ DAEMON_JSON="/etc/docker/daemon.json"
MIRROR_CHECK_TIMEOUT=5
# ---------- 镜像加速状态变量 ----------
MIRROR_STATUS="" # no_file | no_key | empty_array | has_valid_ordered | has_valid_reorder_needed | all_invalid
DEFAULT_STATUS="" # default_unavailable | default_partial | default_all_available
MIRROR_STATUS=""
DEFAULT_STATUS=""
WRITE_DAEMON=false
RESTART_DOCKER=false
REORDER=false
INSERT_DEFAULT=false
HAS_REGISTRY_MIRRORS_KEY=false
AVAILABLE_MIRRORS=() # 可用的默认地址
USER_MIRRORS_AVAILABLE=() # 用户配置中可用的地址
USER_MIRRORS_UNAVAILABLE=() # 用户配置中不可用的地址
USER_MIRRORS_ALL=() # 用户配置所有地址(保持原始顺序)
MIRROR_DETECT_OUTPUT="" # 检测阶段输出给用户的描述
AVAILABLE_MIRRORS=()
USER_MIRRORS_AVAILABLE=()
USER_MIRRORS_UNAVAILABLE=()
USER_MIRRORS_ALL=()
MIRROR_DETECT_OUTPUT=""
# ---------- 其他状态变量 ----------
OS=""; OS_VERSION=""; ARCH=""
@@ -312,7 +312,6 @@ check_docker_mirrors() {
# 8. 判断状态
if [ ${#USER_MIRRORS_AVAILABLE[@]} -gt 0 ]; then
# 检查是否需要重排:是否存在不可用在可用之前
local need_reorder=false
local seen_unavailable=false
for mirror in "${USER_MIRRORS_ALL[@]}"; do
@@ -340,7 +339,6 @@ check_docker_mirrors() {
print_info "用户镜像源配置正常,无需调整"
fi
else
# 用户配置全部不可用
MIRROR_STATUS="all_invalid"
print_warn "用户配置全部不可用"
fi
@@ -352,14 +350,12 @@ check_docker_mirrors() {
generate_mirror_detect_output() {
MIRROR_DETECT_OUTPUT=""
# 如果默认地址全部不可用,直接输出警告
if [ "$DEFAULT_STATUS" = "default_unavailable" ]; then
MIRROR_DETECT_OUTPUT="${MIRROR_DETECT_OUTPUT}${YELLOW}⚠ 所有默认镜像源均不可用,将跳过镜像加速配置${NC}\n"
MIRROR_DETECT_OUTPUT="${MIRROR_DETECT_OUTPUT}如果 Docker 构建失败,请检查网络或手动配置镜像源。\n"
return
fi
# 构建可用地址列表显示
local avail_list=""
for m in "${AVAILABLE_MIRRORS[@]}"; do
avail_list="${avail_list}${m}\n"
@@ -475,7 +471,6 @@ generate_mirror_detect_output() {
;;
esac
# 打印检测输出
echo ""
print_title
print_subtitle "Docker 镜像源检测结果"
@@ -494,7 +489,6 @@ configure_docker_mirrors() {
print_step "配置 Docker 镜像源..."
# 确保 jq 可用
if [ "$HAS_JQ" = false ]; then
print_warn "jq 未安装,尝试安装..."
if ! install_jq; then
@@ -504,7 +498,6 @@ configure_docker_mirrors() {
fi
fi
# 构建新镜像列表
local new_mirrors=()
if [ "$REORDER" = true ]; then
new_mirrors=("${USER_MIRRORS_AVAILABLE[@]}" "${USER_MIRRORS_UNAVAILABLE[@]}")
@@ -524,113 +517,53 @@ configure_docker_mirrors() {
print_info "[反馈] 新镜像列表: ${new_mirrors[*]}"
# ============================================================
# 确保 daemon.json 存在且为有效 JSON
# ============================================================
print_info "[反馈] 检查 daemon.json 状态..."
if [ -f "$DAEMON_JSON" ]; then
print_info "[反馈] 文件存在: $DAEMON_JSON"
if [ -s "$DAEMON_JSON" ]; then
print_info "[反馈] 文件大小: $(stat -c%s "$DAEMON_JSON" 2>/dev/null || stat -f%z "$DAEMON_JSON" 2>/dev/null) bytes"
else
print_warn "[反馈] 文件为空 (0 bytes)"
fi
else
print_info "[反馈] 文件不存在"
fi
if ! ensure_daemon_json_valid; then
print_error "无法创建或修复 daemon.json"
return 1
fi
print_success "[反馈] daemon.json 已就绪 (有效 JSON)"
# ============================================================
# 备份 daemon.json(写入前额外备份)
# ============================================================
local backup_path="${DAEMON_JSON}.bak.$(date +%Y%m%d-%H%M%S)"
cp "$DAEMON_JSON" "$backup_path"
print_info "[反馈] 已备份: $backup_path"
# ============================================================
# 构建 JSON 镜像数组
# ============================================================
print_info "[反馈] 构建 JSON 镜像数组..."
local json_mirrors
json_mirrors=$(printf '%s\n' "${new_mirrors[@]}" | jq -R . | jq -s . 2>/dev/null)
if [ -z "$json_mirrors" ] || [ "$json_mirrors" = "[]" ]; then
print_error "[反馈] 构建 JSON 镜像数组失败或为空"
print_error " new_mirrors 内容: ${new_mirrors[*]}"
return 1
fi
print_info "[反馈] json_mirrors: $json_mirrors"
# ============================================================
# 写入新配置(仅修改 registry-mirrors 字段,保留其他所有字段)
# ============================================================
print_info "[反馈] 执行 jq 写入操作..."
print_info "[反馈] 源文件: $DAEMON_JSON"
print_info "[反馈] 目标文件: ${DAEMON_JSON}.tmp"
if ! jq --argjson mirrors "$json_mirrors" '."registry-mirrors" = $mirrors' \
"$DAEMON_JSON" > "${DAEMON_JSON}.tmp" 2> "${DAEMON_JSON}.error"; then
print_error "[反馈] jq 执行失败"
print_error "[反馈] 错误详情:"
if [ -f "${DAEMON_JSON}.error" ]; then
print_error "[反馈] 错误详情:"
cat "${DAEMON_JSON}.error" | while read -r line; do
print_error " $line"
done
rm -f "${DAEMON_JSON}.error"
fi
print_error "[反馈] 检查文件状态:"
if [ -f "$DAEMON_JSON" ]; then
print_error " 源文件存在,大小: $(stat -c%s "$DAEMON_JSON" 2>/dev/null || stat -f%z "$DAEMON_JSON" 2>/dev/null) bytes"
print_error " 源文件内容预览:"
head -c 200 "$DAEMON_JSON" | while read -r line; do
print_error " $line"
done
else
print_error " 源文件不存在!"
fi
if [ -f "${DAEMON_JSON}.tmp" ]; then
print_error " 临时文件已创建,大小: $(stat -c%s "${DAEMON_JSON}.tmp" 2>/dev/null || stat -f%z "${DAEMON_JSON}.tmp" 2>/dev/null) bytes"
[ -s "${DAEMON_JSON}.tmp" ] && print_error " 临时文件内容: $(cat "${DAEMON_JSON}.tmp")"
fi
rm -f "${DAEMON_JSON}.tmp"
return 1
fi
# 验证临时文件
if [ ! -f "${DAEMON_JSON}.tmp" ]; then
print_error "[反馈] 临时文件未生成: ${DAEMON_JSON}.tmp"
return 1
fi
if [ ! -s "${DAEMON_JSON}.tmp" ]; then
print_error "[反馈] 临时文件为空: ${DAEMON_JSON}.tmp"
if [ ! -f "${DAEMON_JSON}.tmp" ] || [ ! -s "${DAEMON_JSON}.tmp" ]; then
print_error "[反馈] 临时文件为空或不存在"
rm -f "${DAEMON_JSON}.tmp"
return 1
fi
print_success "[反馈] jq 执行成功,临时文件已生成 (大小: $(stat -c%s "${DAEMON_JSON}.tmp" 2>/dev/null || stat -f%z "${DAEMON_JSON}.tmp" 2>/dev/null) bytes)"
# 验证临时文件是否为有效 JSON
if ! jq -e '.' "${DAEMON_JSON}.tmp" >/dev/null 2>&1; then
print_error "[反馈] 生成的临时文件不是有效的 JSON"
print_error "[反馈] 内容预览:"
head -c 500 "${DAEMON_JSON}.tmp" | while read -r line; do
print_error " $line"
done
rm -f "${DAEMON_JSON}.tmp"
return 1
fi
mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON"
print_success "daemon.json 已更新"
print_info "新镜像源列表: ${new_mirrors[*]}"
# 重启 Docker
if [ "$RESTART_DOCKER" = true ]; then
print_step "重启 Docker 服务..."
if systemctl restart docker 2>/dev/null; then
@@ -638,7 +571,6 @@ configure_docker_mirrors() {
sleep 2
else
print_error "Docker 重启失败,请手动重启后重新运行脚本"
print_info "手动重启命令: systemctl restart docker"
exit 1
fi
fi
@@ -779,7 +711,6 @@ print_environment_summary() {
# ---------- 部署计划 ----------
generate_plan() {
PLAN=""
# 按时间先后顺序排列
if [ "$WRITE_DAEMON" = true ]; then
PLAN="${PLAN} • 配置 Docker 镜像源"
if [ "$RESTART_DOCKER" = true ]; then
@@ -936,16 +867,6 @@ do_deploy() {
exit 1
fi
# ----- 停止旧容器 -----
if [ "$CONTAINER_EXISTS" = true ]; then
print_step "停止旧容器..."
if [ "$CONTAINER_RUNNING" = true ]; then
docker stop frpc-console 2>/dev/null || true
fi
docker rm frpc-console 2>/dev/null || true
print_success "旧容器已清理"
fi
# ----- 准备部署目录 -----
print_step "准备部署目录..."
mkdir -p "$DEPLOY_DIR"
@@ -1017,6 +938,23 @@ do_deploy() {
print_info "已标记 ${IMAGE_NAME}:preview"
fi
# ============================================================
# 强制清理旧容器(独立检测,不依赖之前缓存的变量)
# ============================================================
print_step "检查并清理旧容器..."
if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^frpc-console$"; then
print_info "检测到已存在的 frpc-console 容器"
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^frpc-console$"; then
print_info "容器正在运行,停止中..."
docker stop frpc-console 2>/dev/null || true
fi
print_info "删除旧容器..."
docker rm frpc-console 2>/dev/null || true
print_success "旧容器已清理"
else
print_info "未检测到旧容器"
fi
# ----- 启动新容器 -----
print_step "启动 frpc-console 容器..."
docker run -d \
@@ -1146,7 +1084,6 @@ main() {
check_tools
check_container
# ---------- 镜像源检测(拉取代码前,只检测不修改) ----------
check_docker_mirrors
select_channel