#!/bin/bash # SeaweedFS服务管理脚本 # 用法: ./service start|stop|status|restart|help # 定义颜色输出 echo_green() { echo -e "\033[32m$1\033[0m"; } echo_yellow() { echo -e "\033[33m$1\033[0m"; } echo_red() { echo -e "\033[31m$1\033[0m"; } echo_blue() { echo -e "\033[34m$1\033[0m"; } # 日志函数 log_info() { echo_blue "[INFO] $1"; } log_success() { echo_green "[SUCCESS] $1"; } log_warning() { echo_yellow "[WARNING] $1"; } log_error() { echo_red "[ERROR] $1"; } # 获取脚本所在目录的绝对路径 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) # 切换工作目录到脚本所在目录 cd "$SCRIPT_DIR" || { log_error "无法切换到脚本目录" exit 1 } # 检查系统命令 system_commands=("docker" "docker-compose" "openssl") check_system_commands() { for cmd in "${system_commands[@]}"; do if ! command -v "$cmd" &> /dev/null; then log_error "命令 $cmd 未安装,请先安装" return 1 fi done return 0 } # 检查并加载环境变量 load_env_variables() { # 检查必要的命令 if ! check_system_commands; then return 1 fi # 首先尝试加载.envrc中的环境变量 if [ -f ".envrc" ]; then log_info "加载.envrc中的环境变量..." # 检查是否安装了direnv if command -v direnv &> /dev/null; then log_info "使用direnv加载环境变量" eval "$(direnv export bash)" else log_warning "direnv未安装,直接加载.envrc中的环境变量" # 手动加载.envrc中的环境变量,排除包含$(...)的行 while IFS= read -r line || [ -n "$line" ]; do if [[ $line == export* && ! $line =~ \$\(.*\) ]]; then eval "$line" fi done < .envrc fi else log_error ".envrc文件不存在" return 1 fi # 特殊处理S3_SECRET_KEY,因为它包含解密命令 if [ -z "$S3_SECRET_KEY" ] && [ -f "seaweedfs_password.enc" ]; then log_info "解密S3_SECRET_KEY..." # 直接执行解密命令 export S3_SECRET_KEY=$(openssl enc -aes-256-cbc -d -pbkdf2 -iter 10000 -in seaweedfs_password.enc 2>/dev/null) if [ $? -ne 0 ]; then log_error "密码解密失败,请检查密码是否正确" log_error "提示: 可能需要重新初始化密码文件" return 1 fi fi # 定义默认环境变量(如果未设置) export SEAWEEDFS_VERSION=${SEAWEEDFS_VERSION:-4.00} export S3_PORT=${S3_PORT:-8333} export S3_ACCESS_KEY=${S3_ACCESS_KEY:-seaweedfs} export S3_SECRET_KEY=${S3_SECRET_KEY:-seaweedfs} export MASTER_CONTAINER_NAME=${MASTER_CONTAINER_NAME:-seaweedfs-master} export VOLUME_CONTAINER_NAME=${VOLUME_CONTAINER_NAME:-seaweedfs-volume} export FILER_CONTAINER_NAME=${FILER_CONTAINER_NAME:-seaweedfs-filer} export S3_CONTAINER_NAME=${S3_CONTAINER_NAME:-seaweedfs-s3} log_info "环境变量加载完成:" log_info " - SeaweedFS版本: $SEAWEEDFS_VERSION" log_info " - S3端口: $S3_PORT" log_info " - 容器名称:" log_info " * Master: $MASTER_CONTAINER_NAME" log_info " * Volume: $VOLUME_CONTAINER_NAME" log_info " * Filer: $FILER_CONTAINER_NAME" log_info " * S3: $S3_CONTAINER_NAME" return 0 } # 创建必要的目录 create_required_directories() { log_info "创建必要的数据目录..." mkdir -p ./master_data ./volume_data ./filer_data if [ $? -eq 0 ]; then log_success "数据目录创建成功" return 0 else log_error "数据目录创建失败" return 1 fi } # 检查容器是否存在且运行中 is_container_running() { local container_name=$1 docker ps --format "{{.Names}}" | grep -q "^$container_name$" return $? } # 清理旧容器(避免名称冲突) clean_old_containers() { local containers=("$MASTER_CONTAINER_NAME" "$VOLUME_CONTAINER_NAME" "$FILER_CONTAINER_NAME" "$S3_CONTAINER_NAME") local removed_containers=0 log_info "检查并清理可能存在的旧容器..." for container in "${containers[@]}"; do if docker ps -a --format "{{.Names}}" | grep -q "^$container$"; then log_warning "发现旧容器: $container,正在清理..." docker rm -f "$container" > /dev/null if [ $? -eq 0 ]; then log_success "已移除旧容器: $container" removed_containers=$((removed_containers + 1)) else log_error "无法移除容器: $container" fi fi done # 清理可能存在的旧网络 local network_name="$(basename "$SCRIPT_DIR")_default" if docker network ls --format "{{.Name}}" | grep -q "^$network_name$"; then log_warning "发现旧网络: $network_name,正在清理..." docker network rm "$network_name" > /dev/null if [ $? -eq 0 ]; then log_success "已移除旧网络: $network_name" fi fi if [ $removed_containers -gt 0 ]; then log_success "已清理 $removed_containers 个旧容器" else log_info "没有需要清理的旧容器" fi } # 启动服务 start_service() { log_info "启动SeaweedFS服务..." # 加载环境变量 if ! load_env_variables; then log_error "环境变量加载失败,服务启动终止" return 1 fi # 创建必要的目录 if ! create_required_directories; then return 1 fi # 检查docker-compose.yml是否存在 if [ ! -f "docker-compose.yml" ]; then log_error "docker-compose.yml文件不存在" return 1 fi # 清理旧容器,避免名称冲突 clean_old_containers # 启动docker容器 log_info "使用docker-compose启动服务..." docker-compose up -d # 检查启动是否成功 if [ $? -ne 0 ]; then log_error "SeaweedFS服务启动失败" return 1 fi # 等待几秒钟让容器完全启动 log_info "服务正在初始化,请稍候..." sleep 3 # 再次检查状态以确保所有容器都已启动 status_service local status_result=$? if [ $status_result -eq 0 ]; then log_success "SeaweedFS服务启动完成!" log_success "S3服务访问地址: http://localhost:$S3_PORT" return 0 else log_warning "服务可能未完全启动,请检查容器状态" return 1 fi } # 停止服务 stop_service() { log_info "停止SeaweedFS服务..." # 加载环境变量(包括密码验证) if ! load_env_variables; then log_error "环境变量加载失败,服务停止终止" return 1 fi # 首先检查服务是否正在运行 if ! docker-compose ps | grep -q "Up"; then log_info "SeaweedFS服务已经停止或未运行" return 0 fi # 使用docker-compose down停止服务 log_info "使用docker-compose停止所有服务..." docker-compose down if [ $? -eq 0 ]; then log_success "SeaweedFS服务已成功停止" return 0 else log_warning "docker-compose down命令失败,尝试直接停止容器..." # 尝试逐个停止并删除容器 local containers=("$S3_CONTAINER_NAME" "$FILER_CONTAINER_NAME" "$VOLUME_CONTAINER_NAME" "$MASTER_CONTAINER_NAME") local stopped=0 for container in "${containers[@]}"; do if is_container_running "$container"; then log_info "直接停止容器: $container" docker stop "$container" > /dev/null if [ $? -eq 0 ]; then docker rm "$container" > /dev/null log_success "已停止并移除容器: $container" stopped=$((stopped + 1)) else log_error "无法停止容器: $container" fi fi done if [ $stopped -gt 0 ]; then log_success "已成功停止 $stopped 个容器" return 0 else log_error "无法停止任何容器,请检查Docker状态" return 1 fi fi } # 检查服务状态 status_service() { log_info "检查SeaweedFS服务状态..." # 加载环境变量 if ! load_env_variables; then log_error "环境变量加载失败,无法检查状态" return 2 fi # 定义容器数组 local containers=("$MASTER_CONTAINER_NAME" "$VOLUME_CONTAINER_NAME" "$FILER_CONTAINER_NAME" "$S3_CONTAINER_NAME") local container_names=("Master" "Volume" "Filer" "S3") local running_containers=0 local all_containers=${#containers[@]} log_info "详细状态检查:" # 检查每个容器的状态 for i in "${!containers[@]}"; do local container=${containers[$i]} local name=${container_names[$i]} if is_container_running "$container"; then log_success "✅ $name 容器 ($container) 正在运行" running_containers=$((running_containers + 1)) else # 检查容器是否存在但已停止 if docker ps -a --format "{{.Names}}" | grep -q "^$container$"; then log_warning "⚠️ $name 容器 ($container) 已停止" # 获取停止原因 local exit_code=$(docker inspect --format='{{.State.ExitCode}}' "$container") log_warning " 退出代码: $exit_code" else log_error "❌ $name 容器 ($container) 不存在" fi fi done # 输出总体状态 log_info "--------------------------------------------------" if [ $running_containers -eq $all_containers ]; then log_success "✅ SeaweedFS服务完全正常运行" log_success "S3服务访问地址: http://localhost:$S3_PORT" return 0 elif [ $running_containers -gt 0 ]; then log_warning "⚠️ SeaweedFS服务部分运行 ($running_containers/$all_containers 容器运行中)" return 1 else log_error "❌ SeaweedFS服务未运行" return 2 fi } # 重启服务 restart_service() { log_info "重启SeaweedFS服务..." # 先停止服务 stop_service local stop_result=$? # 停止成功后,启动服务 if [ $stop_result -eq 0 ]; then log_info "正在启动SeaweedFS服务..." start_service return $? else log_error "服务停止失败,无法重启" return 1 fi } # 显示帮助信息 show_help() { echo "" echo_blue "📦 SeaweedFS服务管理脚本" echo "" echo "用法: ./service [command]" echo "" echo "命令:" echo " start 启动SeaweedFS服务" echo " stop 停止SeaweedFS服务" echo " status 检查SeaweedFS服务状态" echo " restart 重启SeaweedFS服务" echo " help 显示此帮助信息" echo "" echo "示例:" echo " ./service start # 启动所有SeaweedFS服务" echo " ./service status # 检查服务运行状态" echo " ./service restart # 重启所有服务" echo "" } # 检查命令参数 if [ $# -eq 0 ]; then log_error "请指定命令" show_help exit 1 fi # 执行对应的命令 case "$1" in start) start_service exit $? ;; stop) stop_service exit $? ;; status) status_service exit $? ;; restart) restart_service exit $? ;; help|\ -h|\ --help) show_help exit 0 ;; *) log_error "未知命令 '$1'" show_help exit 1 ;; esac