396 lines
12 KiB
Bash
Executable File
396 lines
12 KiB
Bash
Executable File
#!/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 |