278 lines
7.3 KiB
Bash
278 lines
7.3 KiB
Bash
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
# ============================================================================
|
||
# DevOps AI Stack - 清理脚本
|
||
# 功能:停止和清理所有服务,可选备份数据
|
||
# ============================================================================
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
LOG_FILE="${PROJECT_ROOT}/logs/cleanup-dev-$(date +%Y%m%d_%H%M%S).log"
|
||
|
||
# 创建日志目录
|
||
mkdir -p "${PROJECT_ROOT}/logs"
|
||
|
||
# ============================================================================
|
||
# 日志和颜色输出
|
||
# ============================================================================
|
||
|
||
log() {
|
||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_info() {
|
||
echo -e "\033[36ℹ️ INFO\033[0m: $*" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "\033[32✅ SUCCESS\033[0m: $*" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_warning() {
|
||
echo -e "\033[33⚠️ WARNING\033[0m: $*" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "\033[31❌ ERROR\033[0m: $*" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
# ============================================================================
|
||
# 备份数据卷
|
||
# ============================================================================
|
||
|
||
backup_volumes() {
|
||
log_info "备份关键数据卷..."
|
||
|
||
local backup_dir="${PROJECT_ROOT}/backups/$(date +%Y%m%d_%H%M%S)"
|
||
mkdir -p "$backup_dir"
|
||
|
||
local volumes=(
|
||
"gitea"
|
||
"registry"
|
||
"postgres"
|
||
"redis"
|
||
"minio"
|
||
"prometheus"
|
||
)
|
||
|
||
for volume in "${volumes[@]}"; do
|
||
if docker volume ls | grep -q "$volume"; then
|
||
log_info "备份数据卷: $volume"
|
||
docker run --rm \
|
||
-v "$volume:/source" \
|
||
-v "$backup_dir:/backup" \
|
||
alpine tar czf "/backup/${volume}.tar.gz" -C /source . || true
|
||
fi
|
||
done
|
||
|
||
log_success "数据卷备份完成: $backup_dir"
|
||
}
|
||
|
||
# ============================================================================
|
||
# 停止服务
|
||
# ============================================================================
|
||
|
||
stop_services() {
|
||
log_info "停止所有服务..."
|
||
|
||
local services=(
|
||
"taskflow"
|
||
"ai-visual"
|
||
"ai"
|
||
"observability"
|
||
"dev-cache"
|
||
"core"
|
||
)
|
||
|
||
for service in "${services[@]}"; do
|
||
local compose_file="${PROJECT_ROOT}/infra/compose/${service}.yml"
|
||
if [[ -f "$compose_file" ]]; then
|
||
log_info "停止服务: $service"
|
||
docker compose -f "$compose_file" down >> "$LOG_FILE" 2>&1 || true
|
||
fi
|
||
done
|
||
|
||
log_success "所有服务已停止"
|
||
}
|
||
|
||
# ============================================================================
|
||
# 清理选项
|
||
# ============================================================================
|
||
|
||
cleanup_containers() {
|
||
log_warning "删除所有容器..."
|
||
docker container prune -f >> "$LOG_FILE" 2>&1 || true
|
||
log_success "容器清理完成"
|
||
}
|
||
|
||
cleanup_volumes() {
|
||
log_warning "删除未使用的数据卷..."
|
||
docker volume prune -f >> "$LOG_FILE" 2>&1 || true
|
||
log_success "数据卷清理完成"
|
||
}
|
||
|
||
cleanup_networks() {
|
||
log_warning "删除未使用的网络..."
|
||
docker network prune -f >> "$LOG_FILE" 2>&1 || true
|
||
log_success "网络清理完成"
|
||
}
|
||
|
||
cleanup_all() {
|
||
log_warning "清理所有 Docker 资源..."
|
||
docker system prune -a -f >> "$LOG_FILE" 2>&1 || true
|
||
log_success "全部清理完成"
|
||
}
|
||
|
||
# ============================================================================
|
||
# 恢复数据卷
|
||
# ============================================================================
|
||
|
||
restore_volumes() {
|
||
local backup_dir=$1
|
||
|
||
if [[ ! -d "$backup_dir" ]]; then
|
||
log_error "备份目录不存在: $backup_dir"
|
||
return 1
|
||
fi
|
||
|
||
log_info "从备份恢复数据: $backup_dir"
|
||
|
||
for backup_file in "$backup_dir"/*.tar.gz; do
|
||
local volume_name=$(basename "$backup_file" .tar.gz)
|
||
|
||
log_info "恢复数据卷: $volume_name"
|
||
|
||
# 创建数据卷
|
||
docker volume create "$volume_name" 2>/dev/null || true
|
||
|
||
# 恢复数据
|
||
docker run --rm \
|
||
-v "$volume_name:/target" \
|
||
-v "$backup_dir:/backup" \
|
||
alpine tar xzf "/backup/${volume_name}.tar.gz" -C /target || true
|
||
done
|
||
|
||
log_success "数据恢复完成"
|
||
}
|
||
|
||
# ============================================================================
|
||
# 主函数
|
||
# ============================================================================
|
||
|
||
main() {
|
||
log "=========================================="
|
||
log "🧹 DevOps AI Stack 清理开始"
|
||
log "=========================================="
|
||
|
||
local backup=false
|
||
local remove_containers=false
|
||
local remove_volumes=false
|
||
local remove_networks=false
|
||
local remove_all=false
|
||
local restore_from=""
|
||
|
||
# 解析参数
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--backup)
|
||
backup=true
|
||
shift
|
||
;;
|
||
--remove-containers)
|
||
remove_containers=true
|
||
shift
|
||
;;
|
||
--remove-volumes)
|
||
remove_volumes=true
|
||
shift
|
||
;;
|
||
--remove-networks)
|
||
remove_networks=true
|
||
shift
|
||
;;
|
||
--remove-all)
|
||
remove_all=true
|
||
shift
|
||
;;
|
||
--restore-from)
|
||
restore_from="$2"
|
||
shift 2
|
||
;;
|
||
--help)
|
||
print_help
|
||
exit 0
|
||
;;
|
||
*)
|
||
log_error "未知参数: $1"
|
||
print_help
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# 备份数据
|
||
if [[ "$backup" == true ]]; then
|
||
backup_volumes
|
||
fi
|
||
|
||
# 恢复数据
|
||
if [[ -n "$restore_from" ]]; then
|
||
if ! restore_volumes "$restore_from"; then
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# 停止服务
|
||
stop_services
|
||
|
||
# 清理
|
||
if [[ "$remove_all" == true ]]; then
|
||
cleanup_all
|
||
else
|
||
[[ "$remove_containers" == true ]] && cleanup_containers
|
||
[[ "$remove_volumes" == true ]] && cleanup_volumes
|
||
[[ "$remove_networks" == true ]] && cleanup_networks
|
||
fi
|
||
|
||
# 完成
|
||
log ""
|
||
log "=========================================="
|
||
log_success "✅ 清理完成!"
|
||
log "=========================================="
|
||
log ""
|
||
log "📍 下一步:"
|
||
log " • 重新启动: ./infra/scripts/init-dev.sh"
|
||
log " • 查看备份: ls backups/"
|
||
log " • 查看日志: $LOG_FILE"
|
||
log ""
|
||
}
|
||
|
||
print_help() {
|
||
cat << 'EOF'
|
||
用法: cleanup-dev.sh [选项]
|
||
|
||
选项:
|
||
--backup 备份关键数据卷
|
||
--remove-containers 删除所有容器
|
||
--remove-volumes 删除未使用的数据卷
|
||
--remove-networks 删除未使用的网络
|
||
--remove-all 删除所有 Docker 资源 (谨慎!)
|
||
--restore-from <dir> 从备份恢复数据
|
||
--help 显示此帮助信息
|
||
|
||
示例:
|
||
# 停止服务并备份数据
|
||
./cleanup-dev.sh --backup
|
||
|
||
# 完全清理 (删除所有容器和卷)
|
||
./cleanup-dev.sh --remove-all
|
||
|
||
# 从备份恢复
|
||
./cleanup-dev.sh --restore-from backups/20240101_120000
|
||
|
||
EOF
|
||
}
|
||
|
||
main "$@"
|