175 lines
5.2 KiB
Bash
175 lines
5.2 KiB
Bash
#!/bin/bash
|
||
|
||
# 固定资产管理系统部署脚本
|
||
set -euo pipefail
|
||
|
||
PROJECT_DIR="/opt/equipment-management"
|
||
COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml"
|
||
PROJECT_NAME="equipment-management"
|
||
BACKUP_SCRIPT="$PROJECT_DIR/scripts/backup-equipment.sh"
|
||
SKIP_BACKUP="${SKIP_BACKUP:-0}"
|
||
HEALTHCHECK_ATTEMPTS="${HEALTHCHECK_ATTEMPTS:-12}"
|
||
HEALTHCHECK_INTERVAL_SECONDS="${HEALTHCHECK_INTERVAL_SECONDS:-5}"
|
||
HEALTHCHECK_URL="${HEALTHCHECK_URL:-http://localhost:3000/api/health}"
|
||
EQUIPMENT_CONTAINERS=("equipment-frontend" "equipment-backend" "equipment-mysql")
|
||
LEGACY_CONTAINERS=("shebeiguanli-frontend" "shebeiguanli-backend" "shebeiguanli-mysql")
|
||
LEGACY_STATUS_BEFORE=()
|
||
|
||
get_container_status() {
|
||
local container="$1"
|
||
docker inspect -f '{{.State.Status}}' "$container" 2>/dev/null || printf 'missing\n'
|
||
}
|
||
|
||
record_legacy_container_statuses() {
|
||
local index container status
|
||
|
||
echo ">>> 记录摄影设备借还系统容器状态(仅检查,不操作)..."
|
||
for index in "${!LEGACY_CONTAINERS[@]}"; do
|
||
container="${LEGACY_CONTAINERS[$index]}"
|
||
status="$(get_container_status "$container")"
|
||
LEGACY_STATUS_BEFORE[$index]="$status"
|
||
echo " $container => $status"
|
||
done
|
||
}
|
||
|
||
verify_legacy_container_statuses() {
|
||
local index container before_status after_status
|
||
local failed=0
|
||
|
||
echo ">>> 确认摄影设备借还系统未受影响(仅检查,不操作)..."
|
||
for index in "${!LEGACY_CONTAINERS[@]}"; do
|
||
container="${LEGACY_CONTAINERS[$index]}"
|
||
before_status="${LEGACY_STATUS_BEFORE[$index]}"
|
||
after_status="$(get_container_status "$container")"
|
||
echo " $container => 部署前: $before_status,部署后: $after_status"
|
||
|
||
if [ "$before_status" != "missing" ] && [ "$after_status" != "$before_status" ]; then
|
||
echo " 错误:$container 状态发生变化。部署脚本未对该容器执行任何操作,请立即排查。" >&2
|
||
failed=1
|
||
fi
|
||
done
|
||
|
||
return "$failed"
|
||
}
|
||
|
||
verify_equipment_containers() {
|
||
local container status
|
||
local failed=0
|
||
|
||
echo ">>> 固定资产系统容器状态..."
|
||
for container in "${EQUIPMENT_CONTAINERS[@]}"; do
|
||
status="$(get_container_status "$container")"
|
||
echo " $container => $status"
|
||
if [ "$status" != "running" ]; then
|
||
echo " 错误:固定资产容器 $container 未处于 running 状态。" >&2
|
||
failed=1
|
||
fi
|
||
done
|
||
|
||
return "$failed"
|
||
}
|
||
|
||
wait_for_backend_health() {
|
||
local attempt
|
||
|
||
echo ">>> 检查固定资产系统后端健康状态..."
|
||
for ((attempt = 1; attempt <= HEALTHCHECK_ATTEMPTS; attempt++)); do
|
||
if curl -fsS --max-time 5 "$HEALTHCHECK_URL" >/dev/null; then
|
||
echo " 后端健康检查通过(第 ${attempt}/${HEALTHCHECK_ATTEMPTS} 次)"
|
||
return 0
|
||
fi
|
||
|
||
if [ "$attempt" -lt "$HEALTHCHECK_ATTEMPTS" ]; then
|
||
echo " 第 ${attempt}/${HEALTHCHECK_ATTEMPTS} 次检查失败,${HEALTHCHECK_INTERVAL_SECONDS} 秒后重试..."
|
||
sleep "$HEALTHCHECK_INTERVAL_SECONDS"
|
||
fi
|
||
done
|
||
|
||
echo "后端健康检查失败:${HEALTHCHECK_URL},已尝试 ${HEALTHCHECK_ATTEMPTS} 次。" >&2
|
||
return 1
|
||
}
|
||
|
||
if docker compose version >/dev/null 2>&1; then
|
||
COMPOSE_CMD=(docker compose -p "$PROJECT_NAME" -f "$COMPOSE_FILE")
|
||
elif command -v docker-compose >/dev/null 2>&1; then
|
||
COMPOSE_CMD=(docker-compose -p "$PROJECT_NAME" -f "$COMPOSE_FILE")
|
||
else
|
||
echo "未找到 docker compose / docker-compose,无法部署。"
|
||
exit 1
|
||
fi
|
||
|
||
echo "=========================================="
|
||
echo " 固定资产管理系统 - 安全部署脚本"
|
||
echo "=========================================="
|
||
echo "项目目录: $PROJECT_DIR"
|
||
echo "Compose 文件: $COMPOSE_FILE"
|
||
echo "Compose 项目名: $PROJECT_NAME"
|
||
echo "备份脚本: $BACKUP_SCRIPT"
|
||
echo ""
|
||
|
||
if [ ! -f "$COMPOSE_FILE" ]; then
|
||
echo "未找到 $COMPOSE_FILE"
|
||
exit 1
|
||
fi
|
||
|
||
if ! [[ "$HEALTHCHECK_ATTEMPTS" =~ ^[1-9][0-9]*$ ]]; then
|
||
echo "HEALTHCHECK_ATTEMPTS 必须是正整数: $HEALTHCHECK_ATTEMPTS"
|
||
exit 1
|
||
fi
|
||
|
||
if ! [[ "$HEALTHCHECK_INTERVAL_SECONDS" =~ ^[0-9]+$ ]]; then
|
||
echo "HEALTHCHECK_INTERVAL_SECONDS 必须是非负整数: $HEALTHCHECK_INTERVAL_SECONDS"
|
||
exit 1
|
||
fi
|
||
|
||
cd "$PROJECT_DIR"
|
||
|
||
record_legacy_container_statuses
|
||
|
||
if [ "$SKIP_BACKUP" = "1" ]; then
|
||
echo ">>> 已设置 SKIP_BACKUP=1,跳过备份"
|
||
else
|
||
if [ ! -x "$BACKUP_SCRIPT" ]; then
|
||
echo "备份脚本不存在或不可执行: $BACKUP_SCRIPT"
|
||
exit 1
|
||
fi
|
||
|
||
echo ">>> 先执行固定资产系统备份..."
|
||
"$BACKUP_SCRIPT"
|
||
fi
|
||
|
||
echo ">>> 先构建固定资产系统镜像..."
|
||
"${COMPOSE_CMD[@]}" build
|
||
|
||
echo ">>> 镜像构建成功,开始更新固定资产系统容器..."
|
||
"${COMPOSE_CMD[@]}" up -d --remove-orphans
|
||
|
||
deployment_failed=0
|
||
|
||
if ! wait_for_backend_health; then
|
||
deployment_failed=1
|
||
fi
|
||
|
||
if ! verify_equipment_containers; then
|
||
deployment_failed=1
|
||
fi
|
||
|
||
if ! verify_legacy_container_statuses; then
|
||
deployment_failed=1
|
||
fi
|
||
|
||
if [ "$deployment_failed" -ne 0 ]; then
|
||
echo "固定资产系统部署校验失败,请根据上述错误排查。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
echo " 部署完成"
|
||
SERVER_HOST="${SERVER_HOST:-<server-host>}"
|
||
echo " 固定资产前端: http://$SERVER_HOST"
|
||
echo " 固定资产后端: http://$SERVER_HOST:3000/api"
|
||
echo " 摄影设备前端: http://$SERVER_HOST:8081"
|
||
echo " 摄影设备后端: http://$SERVER_HOST:3001"
|
||
echo "=========================================="
|