初且实现一个以docker启动的seaweedfs对象存储服务
This commit is contained in:
commit
384171ea56
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# 数据目录
|
||||||
|
filer_data/
|
||||||
|
master_data/
|
||||||
|
volume_data/
|
||||||
|
|
||||||
|
# 环境变量文件
|
||||||
|
.envrc
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# 敏感信息
|
||||||
|
seaweedfs_password.enc
|
||||||
|
*_password.enc
|
||||||
|
|
||||||
|
# 备份文件
|
||||||
|
*_bak_*
|
||||||
|
*_backup_*
|
||||||
|
|
||||||
|
# Docker相关
|
||||||
|
.docker/
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
|
||||||
|
# IDE和编辑器文件
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# macOS文件
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# 其他临时文件
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
120
README.md
Normal file
120
README.md
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
# SeaweedFS 文件存储服务
|
||||||
|
|
||||||
|
本目录包含基于 [SeaweedFS](https://github.com/seaweedfs/seaweedfs) 的分布式文件存储服务配置,提供S3兼容接口,用于文件的存储和管理。
|
||||||
|
|
||||||
|
## 服务组件
|
||||||
|
|
||||||
|
SeaweedFS 服务由以下组件组成:
|
||||||
|
|
||||||
|
- **Master Server**: 负责管理卷服务器和文件分配
|
||||||
|
- **Volume Server**: 负责实际存储数据
|
||||||
|
- **Filer**: 提供文件系统接口
|
||||||
|
- **S3 Gateway**: 提供S3兼容接口
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 初始化环境
|
||||||
|
|
||||||
|
首先执行初始化脚本,设置环境变量和创建必要的配置文件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Users/chenqiang/workspace/work/项目记录/202510铁岭县内网文件分发/demo/server/oss
|
||||||
|
./init
|
||||||
|
```
|
||||||
|
|
||||||
|
初始化过程中会提示设置以下参数:
|
||||||
|
- S3服务端口(默认:25003)
|
||||||
|
- S3访问密钥
|
||||||
|
- S3密钥(会加密存储)
|
||||||
|
|
||||||
|
### 2. 启动服务
|
||||||
|
|
||||||
|
使用提供的服务脚本启动SeaweedFS:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./service start
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 停止服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./service stop
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 查看服务状态
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./service status
|
||||||
|
```
|
||||||
|
|
||||||
|
## 环境变量配置
|
||||||
|
|
||||||
|
初始化后,环境变量将保存在 `.envrc` 文件中。主要配置项包括:
|
||||||
|
|
||||||
|
- `SEAWEEDFS_VERSION`: SeaweedFS 版本
|
||||||
|
- `S3_PORT`: S3服务端口
|
||||||
|
- `S3_ACCESS_KEY`: S3访问密钥
|
||||||
|
- `S3_SECRET_KEY`: S3密钥(加密存储)
|
||||||
|
- 各容器名称配置
|
||||||
|
|
||||||
|
## 数据存储
|
||||||
|
|
||||||
|
- **Master数据**: `./master_data/`
|
||||||
|
- **Volume数据**: `./volume_data/`
|
||||||
|
- **Filer数据**: `./filer_data/`
|
||||||
|
|
||||||
|
> **注意**: 数据目录会被 `.gitignore` 忽略,不会提交到代码仓库。
|
||||||
|
|
||||||
|
## S3客户端配置
|
||||||
|
|
||||||
|
使用S3兼容的客户端访问服务时,需要配置以下参数:
|
||||||
|
|
||||||
|
- **Endpoint**: `http://localhost:8333`
|
||||||
|
- **Access Key**: 初始化时设置的值
|
||||||
|
- **Secret Key**: 初始化时设置的值
|
||||||
|
- **Region**: 可以使用任意值,如 `us-east-1`
|
||||||
|
|
||||||
|
## 安全注意事项
|
||||||
|
|
||||||
|
- S3密钥使用OpenSSL加密存储在 `seaweedfs_password.enc` 文件中
|
||||||
|
- 敏感配置文件(如 `.envrc` 和 `seaweedfs_password.enc`)已添加到 `.gitignore`
|
||||||
|
- 建议定期备份数据目录
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
|
||||||
|
1. **服务启动失败**
|
||||||
|
- 检查端口是否被占用
|
||||||
|
- 查看容器日志:`docker logs seaweedfs-master` 等
|
||||||
|
|
||||||
|
2. **S3访问认证失败**
|
||||||
|
- 确认访问密钥和密钥是否正确
|
||||||
|
- 检查 `.envrc` 文件中的配置
|
||||||
|
|
||||||
|
3. **数据丢失**
|
||||||
|
- 确保定期备份数据目录
|
||||||
|
- 避免直接修改数据目录中的文件
|
||||||
|
|
||||||
|
## 维护指南
|
||||||
|
|
||||||
|
### 更新SeaweedFS版本
|
||||||
|
|
||||||
|
1. 修改 `.envrc` 中的 `SEAWEEDFS_VERSION` 值
|
||||||
|
2. 重启服务:`./service restart`
|
||||||
|
|
||||||
|
### 清理旧数据
|
||||||
|
|
||||||
|
> **警告**: 清理数据前请确保已备份重要数据!
|
||||||
|
|
||||||
|
可以通过停止服务并清空数据目录来清理所有数据:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./service stop
|
||||||
|
rm -rf master_data/* volume_data/* filer_data/*
|
||||||
|
./service start
|
||||||
|
```
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
37
docker-compose.yml
Normal file
37
docker-compose.yml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
version: '3.9'
|
||||||
|
|
||||||
|
services:
|
||||||
|
master:
|
||||||
|
image: chrislusf/seaweedfs:${SEAWEEDFS_VERSION:-4.00} # use a remote image
|
||||||
|
container_name: ${MASTER_CONTAINER_NAME:-seaweedfs-master}
|
||||||
|
volumes:
|
||||||
|
- ./master_data:/data
|
||||||
|
command: "master -ip=master -ip.bind=0.0.0.0 -metricsPort=9324"
|
||||||
|
volume:
|
||||||
|
image: chrislusf/seaweedfs:${SEAWEEDFS_VERSION:-4.00} # use a remote image
|
||||||
|
container_name: ${VOLUME_CONTAINER_NAME:-seaweedfs-volume}
|
||||||
|
volumes:
|
||||||
|
- ./volume_data:/data
|
||||||
|
command: 'volume -mserver="master:9333" -ip.bind=0.0.0.0 -port=8080 -metricsPort=9325'
|
||||||
|
depends_on:
|
||||||
|
- master
|
||||||
|
filer:
|
||||||
|
image: chrislusf/seaweedfs:${SEAWEEDFS_VERSION:-4.00} # use a remote image
|
||||||
|
container_name: ${FILER_CONTAINER_NAME:-seaweedfs-filer}
|
||||||
|
volumes:
|
||||||
|
- ./filer_data:/data
|
||||||
|
command: 'filer -master="master:9333" -ip.bind=0.0.0.0 -port=8888 -metricsPort=9326'
|
||||||
|
depends_on:
|
||||||
|
- master
|
||||||
|
- volume
|
||||||
|
s3:
|
||||||
|
image: chrislusf/seaweedfs:${SEAWEEDFS_VERSION:-4.00} # use a remote image
|
||||||
|
container_name: ${S3_CONTAINER_NAME:-seaweedfs-s3}
|
||||||
|
ports:
|
||||||
|
- ${S3_PORT:-8333}:8333 # 只映射S3服务端口给Spring Boot应用访问
|
||||||
|
environment:
|
||||||
|
- S3_ACCESS_KEY=${S3_ACCESS_KEY:-seaweedfs}
|
||||||
|
- S3_SECRET_KEY=${S3_SECRET_KEY:-seaweedfs}
|
||||||
|
command: 's3 -filer="filer:8888" -ip.bind=0.0.0.0 -metricsPort=9327'
|
||||||
|
depends_on:
|
||||||
|
- filer
|
||||||
260
init
Executable file
260
init
Executable file
@ -0,0 +1,260 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# SeaweedFS初始化脚本
|
||||||
|
# 用于初始化或重新初始化SeaweedFS配置环境
|
||||||
|
|
||||||
|
# 获取脚本所在目录的绝对路径
|
||||||
|
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
|
||||||
|
# 切换工作目录到脚本所在目录
|
||||||
|
cd $SCRIPT_DIR
|
||||||
|
|
||||||
|
# 检查必要的命令
|
||||||
|
check_commands() {
|
||||||
|
if ! command -v openssl &> /dev/null; then
|
||||||
|
echo "错误: 未找到openssl命令,请先安装"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v direnv &> /dev/null; then
|
||||||
|
echo "警告: 未找到direnv命令,建议安装以获得最佳体验"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v docker-compose &> /dev/null; then
|
||||||
|
echo "错误: 未找到docker-compose命令,请先安装"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建必要的目录结构
|
||||||
|
create_directories() {
|
||||||
|
echo "创建必要的目录结构..."
|
||||||
|
mkdir -p ./master_data
|
||||||
|
mkdir -p ./volume_data
|
||||||
|
mkdir -p ./filer_data
|
||||||
|
echo "目录结构创建完成"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查docker-compose.yml文件是否存在
|
||||||
|
check_docker_compose() {
|
||||||
|
if [ ! -f "docker-compose.yml" ]; then
|
||||||
|
echo "警告: 未找到docker-compose.yml文件,请确保该文件已存在"
|
||||||
|
echo "提示: 请手动创建或复制正确的docker-compose.yml文件"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 初始化配置文件
|
||||||
|
initialize_files() {
|
||||||
|
# 提示用户输入S3访问密钥(步骤1)
|
||||||
|
default_access_key="seaweedfs"
|
||||||
|
read -p "请输入S3_ACCESS_KEY [$default_access_key]: " s3_access_key
|
||||||
|
|
||||||
|
# 如果用户直接回车,使用默认值
|
||||||
|
if [ -z "$s3_access_key" ]; then
|
||||||
|
s3_access_key="$default_access_key"
|
||||||
|
fi
|
||||||
|
echo "S3_ACCESS_KEY设置为: $s3_access_key"
|
||||||
|
|
||||||
|
# 提示用户输入S3密钥(步骤2)
|
||||||
|
read -s -p "请输入S3_SECRET_KEY: " s3_secret_key
|
||||||
|
echo
|
||||||
|
read -s -p "请再次输入密码确认: " s3_secret_key_confirm
|
||||||
|
echo
|
||||||
|
|
||||||
|
# 验证密码一致性
|
||||||
|
if [ "$s3_secret_key" != "$s3_secret_key_confirm" ]; then
|
||||||
|
echo "错误: 两次输入的密码不一致"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 验证密码强度(可选)
|
||||||
|
if [ ${#s3_secret_key} -lt 8 ]; then
|
||||||
|
echo "警告: 密码长度少于8个字符,建议使用强密码"
|
||||||
|
read -p "是否继续使用此密码?(y/n): " continue
|
||||||
|
if [ "$continue" != "y" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 创建加密文件(步骤3)
|
||||||
|
echo "创建加密的密码文件..."
|
||||||
|
echo "请为加密文件设置一个密码(主密钥):"
|
||||||
|
echo -n "$s3_secret_key" | openssl enc -aes-256-cbc -salt -pbkdf2 -iter 10000 -out seaweedfs_password.enc
|
||||||
|
|
||||||
|
# 检查加密是否成功
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "错误: 创建加密文件失败"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 设置加密文件权限
|
||||||
|
chmod 600 seaweedfs_password.enc
|
||||||
|
echo "加密文件创建成功,权限设置为600"
|
||||||
|
|
||||||
|
# 提示用户输入SeaweedFS镜像版本(步骤4)
|
||||||
|
default_version="4.00"
|
||||||
|
read -p "请输入SeaweedFS镜像版本 [$default_version]: " seaweedfs_version
|
||||||
|
|
||||||
|
# 如果用户直接回车,使用默认值
|
||||||
|
if [ -z "$seaweedfs_version" ]; then
|
||||||
|
seaweedfs_version="$default_version"
|
||||||
|
fi
|
||||||
|
echo "SeaweedFS镜像版本设置为: $seaweedfs_version"
|
||||||
|
|
||||||
|
# 提示用户输入S3服务映射端口号(步骤5)
|
||||||
|
default_port="8333"
|
||||||
|
read -p "请输入S3服务映射端口号 [$default_port]: " s3_port
|
||||||
|
|
||||||
|
# 如果用户直接回车,使用默认值
|
||||||
|
if [ -z "$s3_port" ]; then
|
||||||
|
s3_port="$default_port"
|
||||||
|
fi
|
||||||
|
echo "S3服务映射端口号设置为: $s3_port"
|
||||||
|
|
||||||
|
# 提示用户输入各个容器的名称(步骤6)
|
||||||
|
default_master_name="seaweedfs-master"
|
||||||
|
read -p "请输入master容器名称 [$default_master_name]: " master_container_name
|
||||||
|
|
||||||
|
# 如果用户直接回车,使用默认值
|
||||||
|
if [ -z "$master_container_name" ]; then
|
||||||
|
master_container_name="$default_master_name"
|
||||||
|
fi
|
||||||
|
echo "master容器名称设置为: $master_container_name"
|
||||||
|
|
||||||
|
default_volume_name="seaweedfs-volume"
|
||||||
|
read -p "请输入volume容器名称 [$default_volume_name]: " volume_container_name
|
||||||
|
|
||||||
|
# 如果用户直接回车,使用默认值
|
||||||
|
if [ -z "$volume_container_name" ]; then
|
||||||
|
volume_container_name="$default_volume_name"
|
||||||
|
fi
|
||||||
|
echo "volume容器名称设置为: $volume_container_name"
|
||||||
|
|
||||||
|
default_filer_name="seaweedfs-filer"
|
||||||
|
read -p "请输入filer容器名称 [$default_filer_name]: " filer_container_name
|
||||||
|
|
||||||
|
# 如果用户直接回车,使用默认值
|
||||||
|
if [ -z "$filer_container_name" ]; then
|
||||||
|
filer_container_name="$default_filer_name"
|
||||||
|
fi
|
||||||
|
echo "filer容器名称设置为: $filer_container_name"
|
||||||
|
|
||||||
|
default_s3_name="seaweedfs-s3"
|
||||||
|
read -p "请输入s3容器名称 [$default_s3_name]: " s3_container_name
|
||||||
|
|
||||||
|
# 如果用户直接回车,使用默认值
|
||||||
|
if [ -z "$s3_container_name" ]; then
|
||||||
|
s3_container_name="$default_s3_name"
|
||||||
|
fi
|
||||||
|
echo "s3容器名称设置为: $s3_container_name"
|
||||||
|
|
||||||
|
# 创建.envrc文件
|
||||||
|
echo "创建.envrc配置文件..."
|
||||||
|
cat > .envrc << EOF
|
||||||
|
# SeaweedFS配置环境变量
|
||||||
|
export SEAWEEDFS_VERSION=$seaweedfs_version
|
||||||
|
export S3_PORT=$s3_port
|
||||||
|
export S3_ACCESS_KEY=$s3_access_key
|
||||||
|
export S3_SECRET_KEY=\$(openssl enc -aes-256-cbc -d -pbkdf2 -iter 10000 -in seaweedfs_password.enc)
|
||||||
|
export MASTER_CONTAINER_NAME=$master_container_name
|
||||||
|
export VOLUME_CONTAINER_NAME=$volume_container_name
|
||||||
|
export FILER_CONTAINER_NAME=$filer_container_name
|
||||||
|
export S3_CONTAINER_NAME=$s3_container_name
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 设置.envrc文件权限
|
||||||
|
chmod 600 .envrc
|
||||||
|
echo ".envrc文件创建成功,权限设置为600"
|
||||||
|
|
||||||
|
# 检查docker-compose.yml文件是否存在
|
||||||
|
check_docker_compose
|
||||||
|
|
||||||
|
# 自动执行direnv allow并提供状态反馈
|
||||||
|
if command -v direnv &> /dev/null; then
|
||||||
|
echo ""
|
||||||
|
echo "📝 初始化完成!自动配置环境变量..."
|
||||||
|
echo "正在执行 direnv allow..."
|
||||||
|
if direnv allow > /dev/null 2>&1; then
|
||||||
|
echo "✅ direnv allow 执行成功!环境变量已启用"
|
||||||
|
else
|
||||||
|
echo "❌ direnv allow 执行失败,请手动运行 'direnv allow' 来启用环境变量"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "初始化完成!建议安装direnv以获得更好的使用体验:"
|
||||||
|
echo " macOS: brew install direnv"
|
||||||
|
echo " Linux: apt-get install direnv 或 yum install direnv"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 清理旧的容器(可选)
|
||||||
|
clean_old_containers() {
|
||||||
|
# 检查是否有旧的容器运行
|
||||||
|
echo "检查并清理可能的旧容器..."
|
||||||
|
local containers=("seaweedfs-master" "seaweedfs-volume" "seaweedfs-filer" "seaweedfs-s3" "oss-master-1" "oss-volume-1" "oss-filer-1" "oss-s3-1")
|
||||||
|
|
||||||
|
for container in "${containers[@]}"; do
|
||||||
|
if docker ps -a | grep -q "$container"; then
|
||||||
|
echo "停止并移除容器: $container"
|
||||||
|
docker stop "$container" > /dev/null 2>&1 || true
|
||||||
|
docker rm "$container" > /dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 不清理网络配置,保持与外部网络的兼容性
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
echo "SeaweedFS环境初始化脚本"
|
||||||
|
echo "==================================="
|
||||||
|
|
||||||
|
# 检查必要的命令
|
||||||
|
check_commands
|
||||||
|
|
||||||
|
# 检查文件是否存在
|
||||||
|
if [ -f "seaweedfs_password.enc" ] && [ -f ".envrc" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "检测到seaweedfs_password.enc和.envrc文件已存在"
|
||||||
|
read -p "是否重新初始化?这将覆盖现有配置!(y/n): " reinitialize
|
||||||
|
|
||||||
|
if [ "$reinitialize" != "y" ]; then
|
||||||
|
echo "初始化取消"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 备份现有文件
|
||||||
|
backup_suffix="_bak_$(date +%Y%m%d%H%M%S)"
|
||||||
|
echo "备份现有文件..."
|
||||||
|
cp seaweedfs_password.enc "seaweedfs_password.enc$backup_suffix" 2>/dev/null
|
||||||
|
cp .envrc ".envrc$backup_suffix" 2>/dev/null
|
||||||
|
echo "备份完成"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 创建目录结构
|
||||||
|
create_directories
|
||||||
|
|
||||||
|
# 初始化配置文件
|
||||||
|
while ! initialize_files; do
|
||||||
|
echo "请重新输入配置信息..."
|
||||||
|
done
|
||||||
|
|
||||||
|
# 清理旧的容器
|
||||||
|
clean_old_containers
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "==================================="
|
||||||
|
echo "初始化成功!"
|
||||||
|
echo "使用说明:"
|
||||||
|
echo "1. 使用 './service start' 启动服务"
|
||||||
|
echo "2. 使用 './service stop' 停止服务"
|
||||||
|
echo "3. 使用 './service status' 查看服务状态"
|
||||||
|
echo "4. 使用 './service restart' 重启服务"
|
||||||
|
echo ""
|
||||||
|
echo "S3服务访问地址将为: http://localhost:${s3_port:-8333}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行主函数
|
||||||
|
main
|
||||||
396
service
Executable file
396
service
Executable file
@ -0,0 +1,396 @@
|
|||||||
|
#!/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
|
||||||
Loading…
Reference in New Issue
Block a user