部署环境:

(新)服务器IP地址:172.26.70.184
(旧)数据服务器IP地址:172.26.70.169
minio版本:minio version RELEASE.2022-05-26T05-48-41Z
silo版本:minio version RELEASE.2026-08-04T00-00-00Z

一、Podman容器部署Silo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
podman pull pgsty/minio
podman save -o minio.tar minio:latest
镜像上传其部署服务器
podman load -i /minio.tar

podman run -d \
-p 9000:9000 \
-p 9001:9001 \
--name silo \
-v /data:/data \
-e "MINIO_UPDATE=off" \
-e "MINIO_ROOT_USER=minioadmin" \
-e "MINIO_ROOT_PASSWORD=minioadmin" \
-e "MINIO_BROWSER_REDIRECT_URL=http://172.26.70.184/minio/ui" \
pgsty/minio:latest server /data --console-address ":9001"

二、配置nginx转发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
vim /etc/nginx/nginx.conf

server {
listen 80;
server_name _; # 替换为你的实际域名或IP

# 允许上传任意大小的文件,避免大文件上传被拦截
client_max_body_size 0;

# 必须关闭缓冲,防止 Nginx 将大文件先存到本地再转发导致超时
proxy_buffering off;
proxy_request_buffering off;

# 1. 代理 MinIO API 接口(默认路径)
location /minio/ {
proxy_pass http://127.0.0.1:9000;

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# 保持长连接,适配 S3 协议
proxy_http_version 1.1;
proxy_set_header Connection "";

# 超时配置
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}

# 2. 代理 MinIO Web 控制台
location ^~ /minio/ui {
rewrite ^/minio/ui(/?)(.*) /$2 break;

proxy_pass http://127.0.0.1:9001;

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;

# 核心:动态替换 base 标签
sub_filter '<base href="/"/>' '<base href="/minio/ui/"/>';
sub_filter_once on; # 只替换第一个匹配项
sub_filter_types text/html; # 仅对 HTML 文件进行替换

# 控制台需要支持 WebSocket 升级
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

proxy_connect_timeout 300s;
}
}

三、使用mc本地模式进行数据迁移

配置ssh免密登录

1
2
ssh-keygen -t rsa
ssh-copy-id root@172.16.7.171

将minio远端文件同步到本地

远端minio rwvp目录结构

1
2
3
4
5
6
drwxr-xr-x 158 root root 12288 Apr 16 20:56 hls
drwxr-xr-x 3 root root 4096 Jun 4 17:09 records
drwxr-xr-x 6 root root 4096 Aug 27 11:15 snapshot
drwxr-xr-x 3 root root 4096 Aug 26 2025 standard
drwxr-xr-x 3 root root 4096 Nov 8 2025 tower
drwxr-xr-x 3 root root 4096 Nov 9 2025 vision

使用rsync将远端数据中的部分目录同步到本地

1
rsync -avP root@172.16.7.171:/richfiles/minio/data/rwvp/{hls,standard,tower,vision} /richdata/tmp/rwvp/

使用scp将远端数据中的部分目录同步到本地

1
scp -r root@172.16.7.171:/richfiles/minio/data/rwvp/{hls,standard,tower,vision} /richdata/tmp/rwvp/

使用mc进行上传

服务器安装mcli

mcli下载地址:mcli-20260804000000.0.0-1.x86_64.rpm

1
2
3
wget https://github.com/pgsty/mc/releases/download/RELEASE.2026-08-04T00-00-00Z/mcli-20260804000000.0.0-1.x86_64.rpm
rpm -ivh mcli-20260804000000.0.0-1.x86_64.rpm
/usr/local/bin/mcli --version

使用mc添加minio库

1
2
/usr/local/bin/mcli alias set silo http://127.0.0.1:9000 "minioadmin" "minioadmin"    # 添加新服务器别名
/usr/local/bin/mcli ls silo/rwvp/ # 测试连通性

编写脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/bin/bash
# 脚本: upload_and_clean.sh
# 功能: 将 /data/tmp/rwvp/ 中的文件上传到 silo/rwvp,保持目录结构,
# 上传成功后删除本地文件,并记录所有操作到日志文件。

set -o pipefail

# ========== 配置区 ==========
SOURCE="/data/tmp/rwvp"
TARGET="silo/rwvp"
MCLI="/usr/local/bin/mcli"

# 日志文件路径(默认为脚本所在目录下的 upload.log)
LOG_DIR="$(cd "$(dirname "$0")" && pwd)/logs"
LOG_FILE="$LOG_DIR/upload_$(date +%Y%m%d).log" # 按天分割,或使用固定名称
# 如果想用固定名称,可改为 LOG_FILE="$LOG_DIR/upload.log"

# ========== 初始化日志目录 ==========
if ! mkdir -p "$LOG_DIR" 2>/dev/null; then
echo "警告:无法创建日志目录 $LOG_DIR,将日志输出到标准错误。" >&2
LOG_FILE="/dev/stderr"
fi

# ========== 日志函数 ==========
log_message() {
local status="$1"
local file_path="$2"
local reason="${3:-}"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
if [ -z "$reason" ]; then
echo "$timestamp | $status | $file_path" >> "$LOG_FILE" 2>/dev/null
else
echo "$timestamp | $status | $file_path | $reason" >> "$LOG_FILE" 2>/dev/null
fi
# 如果日志写入失败,则输出到标准错误
if [ $? -ne 0 ]; then
echo "错误:无法写入日志文件 $LOG_FILE" >&2
fi
}

log_success() {
log_message "SUCCESS" "$1"
}

log_failure() {
log_message "FAILED" "$1" "$2"
}

# ========== 环境检查 ==========
if [ ! -d "$SOURCE" ]; then
echo "错误:源目录 $SOURCE 不存在。" >&2
log_failure "SOURCE_DIR" "Directory $SOURCE does not exist"
exit 1
fi

if [ ! -x "$MCLI" ]; then
echo "错误:$MCLI 未找到或不可执行。" >&2
log_failure "MCLI" "Command $MCLI not found or not executable"
exit 1
fi

# ========== 执行上传与清理 ==========
cd "$SOURCE" || exit 1
failure_count=0

while IFS= read -r -d '' file; do
rel_path="${file#./}"
[ -z "$rel_path" ] && continue

echo "正在上传: $rel_path"
if "$MCLI" cp "$SOURCE/$rel_path" "$TARGET/$rel_path" >/dev/null 2>&1; then
# 上传成功,尝试删除本地文件
if rm "$SOURCE/$rel_path"; then
echo "已上传并删除: $rel_path"
log_success "$rel_path"
else
echo "错误:删除本地文件失败: $rel_path" >&2
log_failure "$rel_path" "Upload succeeded but local deletion failed"
failure_count=$((failure_count + 1))
fi
else
echo "错误:上传失败: $rel_path" >&2
log_failure "$rel_path" "Upload failed (mcli cp returned non-zero)"
failure_count=$((failure_count + 1))
fi
done < <(find . -type f -print0)

# ========== 汇总结果 ==========
if [ $failure_count -eq 0 ]; then
echo "所有文件上传并清理成功。"
log_success "ALL" "All files processed successfully"
exit 0
else
echo "有 $failure_count 个文件上传或删除失败,请检查日志 $LOG_FILE" >&2
log_failure "SUMMARY" "Total failures: $failure_count"
exit 1
fi

授权并执行

1
2
chmod +x upload_and_clean.sh
./upload_and_clean.sh