892 lines
26 KiB
Bash
892 lines
26 KiB
Bash
#!/bin/bash
|
|
# 部署脚本 - 若依框架Docker部署方案
|
|
# 实现服务启动和停止功能、服务健康检查、日志查看功能
|
|
# Requirements: 5.4, 5.5
|
|
|
|
set -e
|
|
|
|
# ===========================================
|
|
# 脚本配置
|
|
# ===========================================
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
DOCKER_DIR="$SCRIPT_DIR"
|
|
|
|
# 默认配置
|
|
DEFAULT_ENVIRONMENT="development"
|
|
DEFAULT_ACTION="status"
|
|
FOLLOW_LOGS=false
|
|
VERBOSE=false
|
|
FORCE_RECREATE=false
|
|
TIMEOUT=300
|
|
|
|
# 服务配置
|
|
SERVICES=("anxin-mysql" "anxin-backend" "anxin-frontend")
|
|
ALL_SERVICES="all"
|
|
|
|
# ===========================================
|
|
# 颜色定义
|
|
# ===========================================
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
PURPLE='\033[0;35m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# ===========================================
|
|
# 日志函数
|
|
# ===========================================
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
log_debug() {
|
|
if [[ "$VERBOSE" == "true" ]]; then
|
|
echo -e "${PURPLE}[DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
fi
|
|
}
|
|
|
|
log_step() {
|
|
echo -e "${CYAN}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
# ===========================================
|
|
# 帮助信息
|
|
# ===========================================
|
|
show_help() {
|
|
cat << EOF
|
|
若依框架Docker部署 - 部署管理脚本
|
|
|
|
用法: $0 [选项] [动作] [服务]
|
|
|
|
动作:
|
|
start 启动服务 (默认: 所有服务)
|
|
stop 停止服务 (默认: 所有服务)
|
|
restart 重启服务 (默认: 所有服务)
|
|
status 查看服务状态 (默认动作)
|
|
health 执行健康检查
|
|
logs 查看服务日志
|
|
ps 查看运行中的容器
|
|
down 停止并删除所有容器、网络和卷
|
|
up 启动所有服务 (等同于start all)
|
|
|
|
服务:
|
|
all 所有服务 (默认)
|
|
mysql 数据库服务
|
|
backend 后端服务
|
|
frontend 前端服务
|
|
anxin-mysql 数据库服务 (完整名称)
|
|
anxin-backend 后端服务 (完整名称)
|
|
anxin-frontend 前端服务 (完整名称)
|
|
|
|
选项:
|
|
-e, --env ENV 指定环境 (development|staging|production) [默认: development]
|
|
-f, --follow 跟踪日志输出 (仅用于logs动作)
|
|
-t, --timeout SECONDS 设置操作超时时间 [默认: 300秒]
|
|
--force 强制重新创建容器
|
|
--verbose 显示详细日志
|
|
-h, --help 显示此帮助信息
|
|
|
|
健康检查选项:
|
|
--wait 等待所有服务健康后退出
|
|
--retry COUNT 健康检查重试次数 [默认: 10]
|
|
--interval SECONDS 健康检查间隔 [默认: 30秒]
|
|
|
|
日志选项:
|
|
--tail LINES 显示最后N行日志 [默认: 100]
|
|
--since TIME 显示指定时间后的日志 (如: 2h, 30m)
|
|
|
|
示例:
|
|
$0 # 查看服务状态 (开发环境)
|
|
$0 start # 启动所有服务
|
|
$0 start mysql # 仅启动数据库服务
|
|
$0 stop backend frontend # 停止后端和前端服务
|
|
$0 restart -e production # 重启生产环境所有服务
|
|
$0 health --wait # 等待所有服务健康
|
|
$0 logs backend -f # 跟踪后端服务日志
|
|
$0 logs --tail 50 --since 1h # 查看最近1小时的50行日志
|
|
$0 status -e staging # 查看测试环境状态
|
|
|
|
Requirements Coverage:
|
|
5.4 - 日志输出用于问题排查
|
|
5.5 - 验证服务可用性 (健康检查)
|
|
|
|
EOF
|
|
}
|
|
|
|
# ===========================================
|
|
# 参数解析
|
|
# ===========================================
|
|
parse_args() {
|
|
SERVICES_TO_MANAGE=()
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
start|stop|restart|status|health|logs|ps|down|up)
|
|
ACTION="$1"
|
|
shift
|
|
;;
|
|
-e|--env)
|
|
ENVIRONMENT="$2"
|
|
shift 2
|
|
;;
|
|
-f|--follow)
|
|
FOLLOW_LOGS=true
|
|
shift
|
|
;;
|
|
-t|--timeout)
|
|
TIMEOUT="$2"
|
|
shift 2
|
|
;;
|
|
--force)
|
|
FORCE_RECREATE=true
|
|
shift
|
|
;;
|
|
--verbose)
|
|
VERBOSE=true
|
|
shift
|
|
;;
|
|
--wait)
|
|
WAIT_FOR_HEALTH=true
|
|
shift
|
|
;;
|
|
--retry)
|
|
HEALTH_RETRY_COUNT="$2"
|
|
shift 2
|
|
;;
|
|
--interval)
|
|
HEALTH_CHECK_INTERVAL="$2"
|
|
shift 2
|
|
;;
|
|
--tail)
|
|
LOG_TAIL_LINES="$2"
|
|
shift 2
|
|
;;
|
|
--since)
|
|
LOG_SINCE="$2"
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
all|mysql|backend|frontend|anxin-mysql|anxin-backend|anxin-frontend)
|
|
# 标准化服务名称
|
|
case $1 in
|
|
mysql) SERVICES_TO_MANAGE+=("anxin-mysql") ;;
|
|
backend) SERVICES_TO_MANAGE+=("anxin-backend") ;;
|
|
frontend) SERVICES_TO_MANAGE+=("anxin-frontend") ;;
|
|
all) SERVICES_TO_MANAGE=("${SERVICES[@]}") ;;
|
|
*) SERVICES_TO_MANAGE+=("$1") ;;
|
|
esac
|
|
shift
|
|
;;
|
|
*)
|
|
log_error "未知参数: $1"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# 设置默认值
|
|
ACTION=${ACTION:-$DEFAULT_ACTION}
|
|
ENVIRONMENT=${ENVIRONMENT:-$DEFAULT_ENVIRONMENT}
|
|
HEALTH_RETRY_COUNT=${HEALTH_RETRY_COUNT:-10}
|
|
HEALTH_CHECK_INTERVAL=${HEALTH_CHECK_INTERVAL:-30}
|
|
LOG_TAIL_LINES=${LOG_TAIL_LINES:-100}
|
|
|
|
# 如果没有指定服务,默认为所有服务
|
|
if [[ ${#SERVICES_TO_MANAGE[@]} -eq 0 ]]; then
|
|
SERVICES_TO_MANAGE=("${SERVICES[@]}")
|
|
fi
|
|
}
|
|
|
|
# ===========================================
|
|
# 环境验证和配置
|
|
# ===========================================
|
|
validate_environment() {
|
|
case $ENVIRONMENT in
|
|
development|dev)
|
|
ENVIRONMENT="development"
|
|
;;
|
|
staging|stage)
|
|
ENVIRONMENT="staging"
|
|
;;
|
|
production|prod)
|
|
ENVIRONMENT="production"
|
|
;;
|
|
*)
|
|
log_error "无效的环境: $ENVIRONMENT"
|
|
log_info "支持的环境: development, staging, production"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
log_debug "环境验证通过: $ENVIRONMENT"
|
|
}
|
|
|
|
# 加载环境配置
|
|
load_environment_config() {
|
|
local env_file="${DOCKER_DIR}/environments/.env.${ENVIRONMENT}"
|
|
|
|
if [[ ! -f "$env_file" ]]; then
|
|
log_error "环境配置文件不存在: $env_file"
|
|
exit 1
|
|
fi
|
|
|
|
log_debug "加载环境配置: $ENVIRONMENT"
|
|
source "$env_file"
|
|
|
|
# 设置Docker Compose文件路径
|
|
COMPOSE_FILE="${DOCKER_DIR}/docker-compose.${ENVIRONMENT}.yml"
|
|
ENV_FILE="$env_file"
|
|
|
|
if [[ ! -f "$COMPOSE_FILE" ]]; then
|
|
log_error "Docker Compose文件不存在: $COMPOSE_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# 导出关键环境变量
|
|
export ENVIRONMENT
|
|
export COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-"anxin-${ENVIRONMENT}"}
|
|
|
|
log_debug "环境配置加载完成"
|
|
log_debug "Compose文件: $COMPOSE_FILE"
|
|
log_debug "环境文件: $ENV_FILE"
|
|
log_debug "项目名称: $COMPOSE_PROJECT_NAME"
|
|
}
|
|
|
|
# ===========================================
|
|
# 系统检查
|
|
# ===========================================
|
|
check_prerequisites() {
|
|
log_debug "检查系统依赖..."
|
|
|
|
# 检查Docker
|
|
if ! command -v docker &> /dev/null; then
|
|
log_error "Docker未安装或不在PATH中"
|
|
exit 1
|
|
fi
|
|
|
|
# 检查Docker Compose
|
|
if ! command -v docker-compose &> /dev/null; then
|
|
log_error "Docker Compose未安装或不在PATH中"
|
|
exit 1
|
|
fi
|
|
|
|
# 检查Docker守护进程
|
|
if ! docker info &> /dev/null; then
|
|
log_error "Docker守护进程未运行"
|
|
exit 1
|
|
fi
|
|
|
|
log_debug "系统依赖检查通过"
|
|
}
|
|
|
|
# ===========================================
|
|
# Docker Compose操作封装
|
|
# ===========================================
|
|
compose_cmd() {
|
|
local cmd="$1"
|
|
shift
|
|
|
|
cd "$DOCKER_DIR"
|
|
log_debug "执行: docker-compose -f $COMPOSE_FILE --env-file $ENV_FILE $cmd $*"
|
|
docker-compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" "$cmd" "$@"
|
|
}
|
|
|
|
# ===========================================
|
|
# 服务启动功能 (Requirement 5.5)
|
|
# ===========================================
|
|
start_services() {
|
|
local services_list=("$@")
|
|
|
|
if [[ ${#services_list[@]} -eq 0 ]] || [[ "${services_list[*]}" == "${SERVICES[*]}" ]]; then
|
|
log_step "启动所有服务..."
|
|
services_list=() # 空数组表示所有服务
|
|
else
|
|
log_step "启动指定服务: ${services_list[*]}"
|
|
fi
|
|
|
|
# 创建必要的数据目录
|
|
create_data_directories
|
|
|
|
# 构建启动命令
|
|
local compose_args=("up" "-d")
|
|
|
|
if [[ "$FORCE_RECREATE" == "true" ]]; then
|
|
compose_args+=("--force-recreate")
|
|
fi
|
|
|
|
# 添加服务列表
|
|
if [[ ${#services_list[@]} -gt 0 ]]; then
|
|
compose_args+=("${services_list[@]}")
|
|
fi
|
|
|
|
# 执行启动命令
|
|
log_info "正在启动服务..."
|
|
if compose_cmd "${compose_args[@]}"; then
|
|
log_success "服务启动命令执行成功"
|
|
|
|
# 等待服务启动
|
|
log_info "等待服务启动完成..."
|
|
sleep 10
|
|
|
|
# 检查服务状态
|
|
check_services_status "${services_list[@]}"
|
|
|
|
# 显示访问信息
|
|
show_access_info
|
|
|
|
else
|
|
log_error "服务启动失败"
|
|
log_info "查看详细错误信息:"
|
|
compose_cmd logs --tail 50
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 创建数据目录
|
|
create_data_directories() {
|
|
log_debug "创建必要的数据目录..."
|
|
|
|
local data_dirs=(
|
|
"${DOCKER_DIR}/data/${ENVIRONMENT}/mysql"
|
|
"${DOCKER_DIR}/data/${ENVIRONMENT}/mysql-logs"
|
|
"${DOCKER_DIR}/data/${ENVIRONMENT}/backend-logs"
|
|
"${DOCKER_DIR}/data/${ENVIRONMENT}/uploads"
|
|
"${DOCKER_DIR}/data/${ENVIRONMENT}/nginx-logs"
|
|
)
|
|
|
|
for dir in "${data_dirs[@]}"; do
|
|
if [[ ! -d "$dir" ]]; then
|
|
log_debug "创建目录: $dir"
|
|
mkdir -p "$dir"
|
|
fi
|
|
done
|
|
|
|
# 设置目录权限
|
|
chmod -R 755 "${DOCKER_DIR}/data/${ENVIRONMENT}"
|
|
}
|
|
|
|
# ===========================================
|
|
# 服务停止功能
|
|
# ===========================================
|
|
stop_services() {
|
|
local services_list=("$@")
|
|
|
|
if [[ ${#services_list[@]} -eq 0 ]] || [[ "${services_list[*]}" == "${SERVICES[*]}" ]]; then
|
|
log_step "停止所有服务..."
|
|
services_list=() # 空数组表示所有服务
|
|
else
|
|
log_step "停止指定服务: ${services_list[*]}"
|
|
fi
|
|
|
|
# 构建停止命令
|
|
local compose_args=("stop")
|
|
|
|
# 添加超时参数
|
|
compose_args+=("-t" "$TIMEOUT")
|
|
|
|
# 添加服务列表
|
|
if [[ ${#services_list[@]} -gt 0 ]]; then
|
|
compose_args+=("${services_list[@]}")
|
|
fi
|
|
|
|
# 执行停止命令
|
|
log_info "正在停止服务..."
|
|
if compose_cmd "${compose_args[@]}"; then
|
|
log_success "服务停止成功"
|
|
|
|
# 显示当前状态
|
|
show_services_status
|
|
|
|
else
|
|
log_error "服务停止失败"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ===========================================
|
|
# 服务重启功能
|
|
# ===========================================
|
|
restart_services() {
|
|
local services_list=("$@")
|
|
|
|
log_step "重启服务: ${services_list[*]:-所有服务}"
|
|
|
|
# 先停止服务
|
|
if stop_services "${services_list[@]}"; then
|
|
# 等待一段时间确保服务完全停止
|
|
log_info "等待服务完全停止..."
|
|
sleep 5
|
|
|
|
# 再启动服务
|
|
start_services "${services_list[@]}"
|
|
else
|
|
log_error "重启失败: 服务停止阶段出错"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ===========================================
|
|
# 服务健康检查功能 (Requirement 5.5)
|
|
# ===========================================
|
|
check_services_health() {
|
|
local services_list=("$@")
|
|
local wait_for_health=${WAIT_FOR_HEALTH:-false}
|
|
|
|
if [[ ${#services_list[@]} -eq 0 ]]; then
|
|
services_list=("${SERVICES[@]}")
|
|
fi
|
|
|
|
log_step "执行服务健康检查..."
|
|
|
|
local healthy_services=()
|
|
local unhealthy_services=()
|
|
local retry_count=0
|
|
local max_retries=$HEALTH_RETRY_COUNT
|
|
|
|
while [[ $retry_count -lt $max_retries ]]; do
|
|
healthy_services=()
|
|
unhealthy_services=()
|
|
|
|
log_info "健康检查 (第 $((retry_count + 1))/$max_retries 次)..."
|
|
|
|
for service in "${services_list[@]}"; do
|
|
local container_name="${service}-${ENVIRONMENT}"
|
|
local health_status=$(get_service_health_status "$service")
|
|
|
|
case $health_status in
|
|
"healthy")
|
|
log_success "✓ $service: 健康"
|
|
healthy_services+=("$service")
|
|
;;
|
|
"starting")
|
|
log_warn "⚠ $service: 启动中..."
|
|
unhealthy_services+=("$service")
|
|
;;
|
|
"unhealthy")
|
|
log_error "✗ $service: 不健康"
|
|
unhealthy_services+=("$service")
|
|
;;
|
|
"no-healthcheck")
|
|
# 对于没有健康检查的服务,检查容器是否运行
|
|
if is_service_running "$service"; then
|
|
log_success "✓ $service: 运行中 (无健康检查)"
|
|
healthy_services+=("$service")
|
|
else
|
|
log_error "✗ $service: 未运行"
|
|
unhealthy_services+=("$service")
|
|
fi
|
|
;;
|
|
"not-found")
|
|
log_error "✗ $service: 容器未找到"
|
|
unhealthy_services+=("$service")
|
|
;;
|
|
*)
|
|
log_error "✗ $service: 状态未知 ($health_status)"
|
|
unhealthy_services+=("$service")
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# 如果所有服务都健康,或者不需要等待,则退出循环
|
|
if [[ ${#unhealthy_services[@]} -eq 0 ]] || [[ "$wait_for_health" != "true" ]]; then
|
|
break
|
|
fi
|
|
|
|
# 等待下次检查
|
|
if [[ $retry_count -lt $((max_retries - 1)) ]]; then
|
|
log_info "等待 ${HEALTH_CHECK_INTERVAL} 秒后重试..."
|
|
sleep "$HEALTH_CHECK_INTERVAL"
|
|
fi
|
|
|
|
((retry_count++))
|
|
done
|
|
|
|
# 显示最终结果
|
|
echo "========================================"
|
|
log_info "健康检查结果:"
|
|
log_success "健康服务 (${#healthy_services[@]}): ${healthy_services[*]:-无}"
|
|
|
|
if [[ ${#unhealthy_services[@]} -gt 0 ]]; then
|
|
log_error "不健康服务 (${#unhealthy_services[@]}): ${unhealthy_services[*]}"
|
|
|
|
# 显示不健康服务的详细信息
|
|
for service in "${unhealthy_services[@]}"; do
|
|
show_service_details "$service"
|
|
done
|
|
|
|
return 1
|
|
else
|
|
log_success "所有服务健康检查通过!"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
# 获取服务健康状态
|
|
get_service_health_status() {
|
|
local service="$1"
|
|
local container_name="${service}-${ENVIRONMENT}"
|
|
|
|
# 检查容器是否存在
|
|
if ! docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
|
|
echo "not-found"
|
|
return
|
|
fi
|
|
|
|
# 检查容器是否运行
|
|
if ! docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then
|
|
echo "stopped"
|
|
return
|
|
fi
|
|
|
|
# 获取健康检查状态
|
|
local health_status=$(docker inspect --format='{{.State.Health.Status}}' "$container_name" 2>/dev/null || echo "no-healthcheck")
|
|
echo "$health_status"
|
|
}
|
|
|
|
# 检查服务是否运行
|
|
is_service_running() {
|
|
local service="$1"
|
|
local container_name="${service}-${ENVIRONMENT}"
|
|
|
|
docker ps --format "{{.Names}}" | grep -q "^${container_name}$"
|
|
}
|
|
|
|
# 显示服务详细信息
|
|
show_service_details() {
|
|
local service="$1"
|
|
local container_name="${service}-${ENVIRONMENT}"
|
|
|
|
log_info "服务详细信息: $service"
|
|
echo "----------------------------------------"
|
|
|
|
# 容器状态
|
|
local container_status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null || echo "not-found")
|
|
echo "容器状态: $container_status"
|
|
|
|
# 如果容器存在,显示更多信息
|
|
if [[ "$container_status" != "not-found" ]]; then
|
|
# 启动时间
|
|
local started_at=$(docker inspect --format='{{.State.StartedAt}}' "$container_name" 2>/dev/null)
|
|
echo "启动时间: $started_at"
|
|
|
|
# 重启次数
|
|
local restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)
|
|
echo "重启次数: $restart_count"
|
|
|
|
# 最近日志
|
|
echo "最近日志:"
|
|
docker logs --tail 10 "$container_name" 2>&1 | sed 's/^/ /'
|
|
fi
|
|
|
|
echo "----------------------------------------"
|
|
}
|
|
|
|
# ===========================================
|
|
# 服务状态查看功能
|
|
# ===========================================
|
|
show_services_status() {
|
|
log_step "查看服务状态..."
|
|
|
|
# 显示Docker Compose服务状态
|
|
log_info "Docker Compose服务状态:"
|
|
compose_cmd ps
|
|
|
|
echo ""
|
|
|
|
# 显示详细的容器信息
|
|
log_info "容器详细信息:"
|
|
echo "----------------------------------------"
|
|
printf "%-20s %-15s %-15s %-20s %-10s\n" "服务名称" "容器状态" "健康状态" "端口映射" "重启次数"
|
|
echo "----------------------------------------"
|
|
|
|
for service in "${SERVICES[@]}"; do
|
|
local container_name="${service}-${ENVIRONMENT}"
|
|
|
|
# 获取容器信息
|
|
if docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then
|
|
local status=$(docker inspect --format='{{.State.Status}}' "$container_name" 2>/dev/null)
|
|
local health=$(get_service_health_status "$service")
|
|
local ports=$(docker port "$container_name" 2>/dev/null | tr '\n' ' ' | sed 's/[[:space:]]*$//')
|
|
local restart_count=$(docker inspect --format='{{.RestartCount}}' "$container_name" 2>/dev/null)
|
|
|
|
# 格式化健康状态显示
|
|
case $health in
|
|
"healthy") health="✓ 健康" ;;
|
|
"starting") health="⚠ 启动中" ;;
|
|
"unhealthy") health="✗ 不健康" ;;
|
|
"no-healthcheck") health="- 无检查" ;;
|
|
*) health="? 未知" ;;
|
|
esac
|
|
|
|
printf "%-20s %-15s %-15s %-20s %-10s\n" "$service" "$status" "$health" "${ports:-无}" "$restart_count"
|
|
else
|
|
printf "%-20s %-15s %-15s %-20s %-10s\n" "$service" "未创建" "-" "-" "-"
|
|
fi
|
|
done
|
|
|
|
echo "----------------------------------------"
|
|
|
|
# 显示网络信息
|
|
show_network_info
|
|
|
|
# 显示卷信息
|
|
show_volume_info
|
|
}
|
|
|
|
# 显示网络信息
|
|
show_network_info() {
|
|
log_info "网络信息:"
|
|
local network_name="${COMPOSE_PROJECT_NAME}_default"
|
|
|
|
if docker network ls --format "{{.Name}}" | grep -q "^${network_name}$"; then
|
|
docker network inspect "$network_name" --format "网络名称: {{.Name}}, 驱动: {{.Driver}}, 子网: {{range .IPAM.Config}}{{.Subnet}}{{end}}"
|
|
else
|
|
echo "网络未创建: $network_name"
|
|
fi
|
|
}
|
|
|
|
# 显示卷信息
|
|
show_volume_info() {
|
|
log_info "数据卷信息:"
|
|
echo "----------------------------------------"
|
|
|
|
local volumes=(
|
|
"mysql-data-${ENVIRONMENT}"
|
|
"mysql-logs-${ENVIRONMENT}"
|
|
"backend-logs-${ENVIRONMENT}"
|
|
"backend-uploads-${ENVIRONMENT}"
|
|
"frontend-logs-${ENVIRONMENT}"
|
|
)
|
|
|
|
for volume in "${volumes[@]}"; do
|
|
local full_volume_name="${COMPOSE_PROJECT_NAME}_${volume}"
|
|
if docker volume ls --format "{{.Name}}" | grep -q "^${full_volume_name}$"; then
|
|
local mount_point=$(docker volume inspect "$full_volume_name" --format "{{.Mountpoint}}" 2>/dev/null)
|
|
echo "✓ $volume -> $mount_point"
|
|
else
|
|
echo "✗ $volume (未创建)"
|
|
fi
|
|
done
|
|
|
|
echo "----------------------------------------"
|
|
}
|
|
|
|
# ===========================================
|
|
# 日志查看功能 (Requirement 5.4)
|
|
# ===========================================
|
|
show_services_logs() {
|
|
local services_list=("$@")
|
|
|
|
if [[ ${#services_list[@]} -eq 0 ]]; then
|
|
services_list=("${SERVICES[@]}")
|
|
fi
|
|
|
|
log_step "查看服务日志: ${services_list[*]}"
|
|
|
|
# 构建日志命令
|
|
local compose_args=("logs")
|
|
|
|
# 添加日志选项
|
|
if [[ "$FOLLOW_LOGS" == "true" ]]; then
|
|
compose_args+=("-f")
|
|
fi
|
|
|
|
if [[ -n "$LOG_TAIL_LINES" ]]; then
|
|
compose_args+=("--tail" "$LOG_TAIL_LINES")
|
|
fi
|
|
|
|
if [[ -n "$LOG_SINCE" ]]; then
|
|
compose_args+=("--since" "$LOG_SINCE")
|
|
fi
|
|
|
|
# 添加时间戳
|
|
compose_args+=("-t")
|
|
|
|
# 添加服务列表
|
|
compose_args+=("${services_list[@]}")
|
|
|
|
# 执行日志命令
|
|
log_info "日志查看选项: tail=${LOG_TAIL_LINES:-all}, since=${LOG_SINCE:-all}, follow=${FOLLOW_LOGS}"
|
|
|
|
if [[ "$FOLLOW_LOGS" == "true" ]]; then
|
|
log_info "开始跟踪日志 (按 Ctrl+C 退出)..."
|
|
fi
|
|
|
|
compose_cmd "${compose_args[@]}"
|
|
}
|
|
|
|
# ===========================================
|
|
# 完整清理功能
|
|
# ===========================================
|
|
down_all_services() {
|
|
log_step "停止并清理所有服务..."
|
|
|
|
log_warn "这将停止所有容器并删除网络,但保留数据卷"
|
|
read -p "确认继续? (y/N): " -n 1 -r
|
|
echo
|
|
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
log_info "操作已取消"
|
|
return 0
|
|
fi
|
|
|
|
# 执行down命令
|
|
if compose_cmd down --remove-orphans; then
|
|
log_success "服务清理完成"
|
|
|
|
# 显示清理后的状态
|
|
log_info "清理后状态:"
|
|
compose_cmd ps
|
|
|
|
else
|
|
log_error "服务清理失败"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ===========================================
|
|
# 显示访问信息
|
|
# ===========================================
|
|
show_access_info() {
|
|
log_info "服务访问信息:"
|
|
echo "========================================"
|
|
echo "环境: $ENVIRONMENT"
|
|
echo "----------------------------------------"
|
|
echo "前端应用: http://localhost:${FRONTEND_PORT:-80}"
|
|
echo "后端API: http://localhost:${BACKEND_PORT:-8080}"
|
|
echo "数据库: localhost:${DB_PORT:-3306}"
|
|
echo "----------------------------------------"
|
|
echo "管理命令:"
|
|
echo " 查看状态: $0 status -e $ENVIRONMENT"
|
|
echo " 查看日志: $0 logs -e $ENVIRONMENT"
|
|
echo " 健康检查: $0 health -e $ENVIRONMENT"
|
|
echo " 停止服务: $0 stop -e $ENVIRONMENT"
|
|
echo "========================================"
|
|
}
|
|
|
|
# ===========================================
|
|
# 检查服务状态 (内部使用)
|
|
# ===========================================
|
|
check_services_status() {
|
|
local services_list=("$@")
|
|
|
|
if [[ ${#services_list[@]} -eq 0 ]]; then
|
|
services_list=("${SERVICES[@]}")
|
|
fi
|
|
|
|
log_info "检查服务启动状态..."
|
|
|
|
local running_services=()
|
|
local failed_services=()
|
|
|
|
for service in "${services_list[@]}"; do
|
|
if is_service_running "$service"; then
|
|
running_services+=("$service")
|
|
log_success "✓ $service: 运行中"
|
|
else
|
|
failed_services+=("$service")
|
|
log_error "✗ $service: 未运行"
|
|
fi
|
|
done
|
|
|
|
if [[ ${#failed_services[@]} -gt 0 ]]; then
|
|
log_warn "部分服务启动失败: ${failed_services[*]}"
|
|
log_info "建议执行健康检查: $0 health -e $ENVIRONMENT"
|
|
fi
|
|
}
|
|
|
|
# ===========================================
|
|
# 主函数
|
|
# ===========================================
|
|
main() {
|
|
# 显示脚本信息
|
|
log_info "若依框架Docker部署 - 部署管理脚本"
|
|
log_info "脚本版本: 1.0.0"
|
|
log_info "执行时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
|
|
# 解析参数
|
|
parse_args "$@"
|
|
|
|
# 验证环境
|
|
validate_environment
|
|
|
|
# 加载环境配置
|
|
load_environment_config
|
|
|
|
# 检查系统依赖
|
|
check_prerequisites
|
|
|
|
# 显示当前配置
|
|
log_debug "当前配置:"
|
|
log_debug " 动作: $ACTION"
|
|
log_debug " 环境: $ENVIRONMENT"
|
|
log_debug " 服务: ${SERVICES_TO_MANAGE[*]}"
|
|
log_debug " 超时: ${TIMEOUT}秒"
|
|
|
|
# 根据动作执行相应操作
|
|
case $ACTION in
|
|
start|up)
|
|
start_services "${SERVICES_TO_MANAGE[@]}"
|
|
;;
|
|
stop)
|
|
stop_services "${SERVICES_TO_MANAGE[@]}"
|
|
;;
|
|
restart)
|
|
restart_services "${SERVICES_TO_MANAGE[@]}"
|
|
;;
|
|
status|ps)
|
|
show_services_status
|
|
;;
|
|
health)
|
|
check_services_health "${SERVICES_TO_MANAGE[@]}"
|
|
;;
|
|
logs)
|
|
show_services_logs "${SERVICES_TO_MANAGE[@]}"
|
|
;;
|
|
down)
|
|
down_all_services
|
|
;;
|
|
*)
|
|
log_error "未知动作: $ACTION"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
local exit_code=$?
|
|
|
|
if [[ $exit_code -eq 0 ]]; then
|
|
log_success "操作完成!"
|
|
else
|
|
log_error "操作失败 (退出代码: $exit_code)"
|
|
fi
|
|
|
|
exit $exit_code
|
|
}
|
|
|
|
# ===========================================
|
|
# 错误处理
|
|
# ===========================================
|
|
trap 'log_error "脚本执行被中断"; exit 1' INT TERM
|
|
|
|
# 执行主函数
|
|
main "$@" |