591 lines
13 KiB
Markdown
591 lines
13 KiB
Markdown
# MinIO Client (mc) 使用指南
|
||
|
||
本目录包含在 Woodpecker CI 中使用 MinIO Client (mc) 操作 RustFS/S3 对象存储的完整示例。
|
||
|
||
## 📋 目录
|
||
|
||
- [mc 简介](#mc-简介)
|
||
- [目录结构](#目录结构)
|
||
- [快速开始](#快速开始)
|
||
- [常用功能](#常用功能)
|
||
- [上传文件](#上传文件)
|
||
- [下载文件](#下载文件)
|
||
- [列举文件](#列举文件)
|
||
- [删除文件](#删除文件)
|
||
- [生成临时下载链接](#生成临时下载链接)
|
||
- [设置公开访问](#设置公开访问)
|
||
- [清理旧文件](#清理旧文件)
|
||
- [临时链接详解](#临时链接详解)
|
||
- [命令速查表](#命令速查表)
|
||
- [最佳实践](#最佳实践)
|
||
|
||
---
|
||
|
||
## mc 简介
|
||
|
||
MinIO Client (mc) 是一个功能强大的命令行工具,用于操作 S3 兼容的对象存储服务。
|
||
|
||
### 为什么选择 mc?
|
||
|
||
✅ **功能全面**: 支持上传、下载、删除、同步、生成临时链接等
|
||
✅ **跨平台**: 支持 Linux、macOS、Windows
|
||
✅ **兼容性好**: 完全兼容 S3 API 和 RustFS
|
||
✅ **易于使用**: 命令简洁,类似传统的文件操作命令
|
||
✅ **可验证**: 可获取 ETag、VersionId 等元数据
|
||
✅ **支持预签名**: 可生成无需认证的临时下载链接
|
||
|
||
---
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
mc/
|
||
├── README.md # 本文档
|
||
├── linux/
|
||
│ └── woodpecker.yml # Linux 环境完整示例
|
||
└── macos/
|
||
└── woodpecker.yml # macOS 环境完整示例
|
||
```
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
### 安装 mc
|
||
|
||
**Linux:**
|
||
```bash
|
||
curl -sSL https://dl.min.io/client/mc/release/linux-amd64/mc \
|
||
-o /usr/local/bin/mc
|
||
chmod +x /usr/local/bin/mc
|
||
```
|
||
|
||
**macOS (Intel):**
|
||
```bash
|
||
curl -sSL https://dl.min.io/client/mc/release/darwin-amd64/mc \
|
||
-o /usr/local/bin/mc
|
||
chmod +x /usr/local/bin/mc
|
||
```
|
||
|
||
**macOS (Apple Silicon):**
|
||
```bash
|
||
curl -sSL https://dl.min.io/client/mc/release/darwin-arm64/mc \
|
||
-o /usr/local/bin/mc
|
||
chmod +x /usr/local/bin/mc
|
||
```
|
||
|
||
### 配置 mc 别名
|
||
|
||
```bash
|
||
# 配置 RustFS 连接
|
||
mc alias set rustfs https://your-rustfs-server:9000 YOUR_ACCESS_KEY YOUR_SECRET_KEY
|
||
|
||
# 验证配置
|
||
mc admin info rustfs
|
||
```
|
||
|
||
---
|
||
|
||
## 常用功能
|
||
|
||
### 上传文件
|
||
|
||
#### 上传单个文件
|
||
```bash
|
||
mc cp local-file.txt rustfs/my-bucket/path/remote-file.txt
|
||
```
|
||
|
||
#### 上传整个目录
|
||
```bash
|
||
mc cp --recursive ./dist/ rustfs/my-bucket/website/
|
||
```
|
||
|
||
#### 上传时删除源路径前缀
|
||
```bash
|
||
# 将 dist/css/style.css 上传为 css/style.css
|
||
mc mirror --overwrite ./dist/ rustfs/my-bucket/website/
|
||
```
|
||
|
||
#### 上传并获取 ETag
|
||
```bash
|
||
mc cp myfile.jar rustfs/my-bucket/builds/
|
||
mc stat rustfs/my-bucket/builds/myfile.jar | grep ETag
|
||
```
|
||
|
||
---
|
||
|
||
### 下载文件
|
||
|
||
#### 下载单个文件
|
||
```bash
|
||
mc cp rustfs/my-bucket/path/file.txt ./local-file.txt
|
||
```
|
||
|
||
#### 下载整个目录
|
||
```bash
|
||
mc cp --recursive rustfs/my-bucket/backup/ ./local-backup/
|
||
```
|
||
|
||
#### 下载最新版本
|
||
```bash
|
||
mc cp rustfs/my-bucket/versioned-file.txt ./
|
||
```
|
||
|
||
---
|
||
|
||
### 列举文件
|
||
|
||
#### 列出 bucket 内容
|
||
```bash
|
||
# 列出顶层文件
|
||
mc ls rustfs/my-bucket/
|
||
|
||
# 递归列出所有文件
|
||
mc ls --recursive rustfs/my-bucket/
|
||
|
||
# 列出并显示详细信息
|
||
mc ls --recursive --summarize rustfs/my-bucket/
|
||
```
|
||
|
||
#### 按时间过滤
|
||
```bash
|
||
# 列出最近 7 天修改的文件
|
||
mc ls --recursive --newer-than 7d rustfs/my-bucket/
|
||
|
||
# 列出 30 天前的文件
|
||
mc ls --recursive --older-than 30d rustfs/my-bucket/
|
||
```
|
||
|
||
---
|
||
|
||
### 删除文件
|
||
|
||
#### 删除单个文件
|
||
```bash
|
||
mc rm rustfs/my-bucket/path/file.txt
|
||
```
|
||
|
||
#### 删除整个目录
|
||
```bash
|
||
mc rm --recursive --force rustfs/my-bucket/old-builds/
|
||
```
|
||
|
||
#### 按时间删除
|
||
```bash
|
||
# 删除 30 天前的文件
|
||
mc rm --recursive --force --older-than 30d rustfs/my-bucket/builds/
|
||
|
||
# 删除 7 天前的日志
|
||
mc rm --recursive --force --older-than 7d rustfs/my-bucket/logs/
|
||
```
|
||
|
||
#### 按模式删除
|
||
```bash
|
||
# 删除所有 .log 文件
|
||
mc rm --recursive --force rustfs/my-bucket/logs/*.log
|
||
|
||
# 删除特定日期的构建
|
||
mc rm --recursive --force rustfs/my-bucket/builds/20241001/
|
||
```
|
||
|
||
---
|
||
|
||
### 生成临时下载链接
|
||
|
||
#### 基本用法(默认 7 天有效期)
|
||
```bash
|
||
mc share download rustfs/my-bucket/path/file.jar
|
||
```
|
||
|
||
**输出示例:**
|
||
```
|
||
URL: https://your-server:9000/my-bucket/path/file.jar?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
|
||
Expire: 7 days 0 hours 0 minutes 0 seconds
|
||
Share: https://your-server:9000/my-bucket/path/file.jar?X-Amz-Algorithm=...
|
||
```
|
||
|
||
#### 自定义有效期
|
||
|
||
##### 按小时
|
||
```bash
|
||
# 1 小时
|
||
mc share download --expire 1h rustfs/my-bucket/file.jar
|
||
|
||
# 6 小时
|
||
mc share download --expire 6h rustfs/my-bucket/file.jar
|
||
|
||
# 24 小时(1天)
|
||
mc share download --expire 24h rustfs/my-bucket/file.jar
|
||
```
|
||
|
||
##### 按天
|
||
```bash
|
||
# 1 天
|
||
mc share download --expire 1d rustfs/my-bucket/file.jar
|
||
|
||
# 3 天
|
||
mc share download --expire 3d rustfs/my-bucket/file.jar
|
||
|
||
# 7 天(最大值)
|
||
mc share download --expire 7d rustfs/my-bucket/file.jar
|
||
|
||
# 14 天(如果服务器支持)
|
||
mc share download --expire 14d rustfs/my-bucket/file.jar
|
||
```
|
||
|
||
##### 按分钟(短期分享)
|
||
```bash
|
||
# 30 分钟
|
||
mc share download --expire 30m rustfs/my-bucket/temp-file.txt
|
||
|
||
# 5 分钟(快速分享)
|
||
mc share download --expire 5m rustfs/my-bucket/quick-share.pdf
|
||
```
|
||
|
||
#### 批量生成链接
|
||
```bash
|
||
# 为目录下所有文件生成链接
|
||
mc ls rustfs/my-bucket/releases/ | awk '{print $NF}' | while read file; do
|
||
echo "Generating link for: $file"
|
||
mc share download --expire 7d rustfs/my-bucket/releases/$file
|
||
done
|
||
```
|
||
|
||
#### 生成链接并保存
|
||
```bash
|
||
# 保存到文件
|
||
mc share download --expire 7d rustfs/my-bucket/app.jar > download-link.txt
|
||
|
||
# 提取纯 URL
|
||
mc share download --expire 7d rustfs/my-bucket/app.jar | grep "Share:" | awk '{print $2}'
|
||
```
|
||
|
||
---
|
||
|
||
### 设置公开访问
|
||
|
||
#### 设置 bucket 为公开可读(永久链接)
|
||
```bash
|
||
# 公开整个 bucket
|
||
mc anonymous set download rustfs/my-bucket/
|
||
|
||
# 公开特定路径
|
||
mc anonymous set download rustfs/my-bucket/public/
|
||
|
||
# 取消公开访问
|
||
mc anonymous set none rustfs/my-bucket/
|
||
```
|
||
|
||
**公开访问后的 URL 格式:**
|
||
```
|
||
https://your-server:9000/my-bucket/path/file.jar
|
||
```
|
||
|
||
不需要签名参数,可直接访问。
|
||
|
||
---
|
||
|
||
### 清理旧文件
|
||
|
||
#### 按时间自动清理
|
||
```bash
|
||
# 清理 30 天前的构建
|
||
mc rm --recursive --force --older-than 30d rustfs/my-bucket/builds/
|
||
|
||
# 清理 7 天前的日志
|
||
mc rm --recursive --force --older-than 7d rustfs/my-bucket/logs/
|
||
|
||
# 清理 90 天前的备份
|
||
mc rm --recursive --force --older-than 90d rustfs/my-bucket/backups/
|
||
```
|
||
|
||
#### 保留最近 N 个版本
|
||
```bash
|
||
# 列出文件按时间排序
|
||
mc ls --recursive rustfs/my-bucket/releases/ | sort -k1,1 -r | tail -n +11 | awk '{print $NF}' | while read file; do
|
||
mc rm rustfs/my-bucket/releases/$file
|
||
done
|
||
```
|
||
|
||
---
|
||
|
||
## 临时链接详解
|
||
|
||
### 临时链接的工作原理
|
||
|
||
临时下载链接(预签名 URL)使用 AWS Signature V4 算法生成,包含:
|
||
- 访问凭证(已签名)
|
||
- 过期时间戳
|
||
- 请求参数的签名
|
||
|
||
**优势:**
|
||
- ✅ 无需认证即可下载
|
||
- ✅ 可设置精确的过期时间
|
||
- ✅ 可分享给任何人
|
||
- ✅ 自动过期,安全可控
|
||
|
||
### 有效期时间单位
|
||
|
||
| 单位 | 说明 | 示例 |
|
||
|------|------|------|
|
||
| `m` | 分钟 (minutes) | `30m` = 30分钟 |
|
||
| `h` | 小时 (hours) | `6h` = 6小时 |
|
||
| `d` | 天 (days) | `7d` = 7天 |
|
||
|
||
### 有效期限制
|
||
|
||
- **最小值**: 1 分钟 (`1m`)
|
||
- **默认值**: 7 天 (`7d`)
|
||
- **最大值**: 取决于 S3 服务器配置(通常为 7 天)
|
||
|
||
### 常见使用场景
|
||
|
||
#### 场景 1: 内部快速分享(短期)
|
||
```bash
|
||
# 5分钟有效,用于即时分享
|
||
mc share download --expire 5m rustfs/bucket/temp-file.zip
|
||
```
|
||
|
||
#### 场景 2: 客户下载(中期)
|
||
```bash
|
||
# 24小时有效,给客户足够时间下载
|
||
mc share download --expire 24h rustfs/bucket/client-delivery.zip
|
||
```
|
||
|
||
#### 场景 3: 归档访问(长期)
|
||
```bash
|
||
# 7天有效,用于归档文件的临时访问
|
||
mc share download --expire 7d rustfs/bucket/archive/report.pdf
|
||
```
|
||
|
||
#### 场景 4: 公开发布(永久)
|
||
```bash
|
||
# 不设置过期时间,使用公开访问
|
||
mc anonymous set download rustfs/bucket/public/
|
||
# 现在可以直接访问: https://server/bucket/public/file.jar
|
||
```
|
||
|
||
---
|
||
|
||
## 命令速查表
|
||
|
||
### 文件操作
|
||
|
||
| 操作 | 命令 |
|
||
|------|------|
|
||
| 上传文件 | `mc cp file.txt rustfs/bucket/` |
|
||
| 上传目录 | `mc cp --recursive ./dir/ rustfs/bucket/` |
|
||
| 下载文件 | `mc cp rustfs/bucket/file.txt ./` |
|
||
| 下载目录 | `mc cp --recursive rustfs/bucket/dir/ ./` |
|
||
| 删除文件 | `mc rm rustfs/bucket/file.txt` |
|
||
| 删除目录 | `mc rm --recursive --force rustfs/bucket/dir/` |
|
||
| 列出文件 | `mc ls rustfs/bucket/` |
|
||
| 递归列出 | `mc ls --recursive rustfs/bucket/` |
|
||
| 查看信息 | `mc stat rustfs/bucket/file.txt` |
|
||
|
||
### 临时链接
|
||
|
||
| 操作 | 命令 |
|
||
|------|------|
|
||
| 生成链接(默认7天) | `mc share download rustfs/bucket/file.jar` |
|
||
| 1小时有效 | `mc share download --expire 1h rustfs/bucket/file.jar` |
|
||
| 1天有效 | `mc share download --expire 1d rustfs/bucket/file.jar` |
|
||
| 7天有效 | `mc share download --expire 7d rustfs/bucket/file.jar` |
|
||
| 30分钟有效 | `mc share download --expire 30m rustfs/bucket/file.jar` |
|
||
|
||
### 清理操作
|
||
|
||
| 操作 | 命令 |
|
||
|------|------|
|
||
| 删除30天前文件 | `mc rm --recursive --older-than 30d rustfs/bucket/` |
|
||
| 删除7天前文件 | `mc rm --recursive --older-than 7d rustfs/bucket/` |
|
||
| 删除所有.log | `mc rm --recursive rustfs/bucket/*.log` |
|
||
| 强制删除 | `mc rm --recursive --force rustfs/bucket/dir/` |
|
||
|
||
### 权限操作
|
||
|
||
| 操作 | 命令 |
|
||
|------|------|
|
||
| 设置公开下载 | `mc anonymous set download rustfs/bucket/` |
|
||
| 设置公开上传 | `mc anonymous set upload rustfs/bucket/` |
|
||
| 设置公开读写 | `mc anonymous set public rustfs/bucket/` |
|
||
| 取消公开访问 | `mc anonymous set none rustfs/bucket/` |
|
||
| 查看权限 | `mc anonymous get rustfs/bucket/` |
|
||
|
||
---
|
||
|
||
## 最佳实践
|
||
|
||
### 1. 密钥管理
|
||
```yaml
|
||
# ✅ 使用 Woodpecker Secrets
|
||
environment:
|
||
AWS_ACCESS_KEY_ID:
|
||
from_secret: AWS_ACCESS_KEY_ID
|
||
AWS_SECRET_ACCESS_KEY:
|
||
from_secret: AWS_SECRET_ACCESS_KEY
|
||
|
||
# ❌ 不要硬编码密钥
|
||
environment:
|
||
AWS_ACCESS_KEY_ID: "AKIAIOSFODNN7EXAMPLE"
|
||
```
|
||
|
||
### 2. 错误处理
|
||
```bash
|
||
set -e # 遇到错误立即退出
|
||
|
||
# 上传并验证
|
||
mc cp file.jar rustfs/bucket/
|
||
if mc stat rustfs/bucket/file.jar &>/dev/null; then
|
||
echo "✅ Upload successful"
|
||
else
|
||
echo "❌ Upload failed"
|
||
exit 1
|
||
fi
|
||
```
|
||
|
||
### 3. 按日期组织
|
||
```bash
|
||
# 按日期创建目录
|
||
BUILD_DATE=$(date +%Y%m%d)
|
||
mc cp dist/ rustfs/bucket/builds/${BUILD_DATE}/
|
||
```
|
||
|
||
### 4. 定期清理
|
||
```bash
|
||
# 在 CI 中定期清理旧构建
|
||
mc rm --recursive --older-than 30d rustfs/bucket/builds/
|
||
```
|
||
|
||
### 5. 生成有意义的链接
|
||
```bash
|
||
# 保存链接到文件,方便分享
|
||
BUILD_ID=${CI_PIPELINE_NUMBER}
|
||
mc share download --expire 7d rustfs/bucket/app-${BUILD_ID}.jar > download-${BUILD_ID}.txt
|
||
```
|
||
|
||
### 6. 验证上传
|
||
```bash
|
||
# 上传后获取 ETag 验证完整性
|
||
mc cp file.jar rustfs/bucket/
|
||
ETAG=$(mc stat rustfs/bucket/file.jar | grep ETag | awk '{print $2}')
|
||
echo "File uploaded with ETag: $ETAG"
|
||
```
|
||
|
||
---
|
||
|
||
## 使用示例
|
||
|
||
### 示例 1: 上传并生成下载链接
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
set -e
|
||
|
||
# 配置
|
||
mc alias set rustfs https://s3.example.com:9000 $ACCESS_KEY $SECRET_KEY
|
||
|
||
# 上传文件
|
||
mc cp myapp.jar rustfs/releases/v1.0.0/myapp.jar
|
||
|
||
# 生成 24 小时有效的下载链接
|
||
DOWNLOAD_LINK=$(mc share download --expire 24h rustfs/releases/v1.0.0/myapp.jar | grep Share | awk '{print $2}')
|
||
|
||
echo "✅ 上传成功!"
|
||
echo "📥 下载链接: $DOWNLOAD_LINK"
|
||
echo "⏰ 有效期: 24 小时"
|
||
```
|
||
|
||
### 示例 2: 清理旧构建并保留最新 10 个
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
set -e
|
||
|
||
mc alias set rustfs https://s3.example.com:9000 $ACCESS_KEY $SECRET_KEY
|
||
|
||
# 列出所有构建,按时间排序,删除 30 天前的
|
||
echo "🧹 清理旧构建..."
|
||
mc rm --recursive --older-than 30d rustfs/builds/
|
||
|
||
# 统计剩余构建数
|
||
REMAINING=$(mc ls --recursive rustfs/builds/ | wc -l)
|
||
echo "✅ 清理完成,剩余 $REMAINING 个构建"
|
||
```
|
||
|
||
### 示例 3: 批量生成下载链接
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
set -e
|
||
|
||
mc alias set rustfs https://s3.example.com:9000 $ACCESS_KEY $SECRET_KEY
|
||
|
||
echo "# 下载链接汇总" > links.md
|
||
echo "生成时间: $(date)" >> links.md
|
||
echo "" >> links.md
|
||
|
||
# 为 releases 目录下所有文件生成链接
|
||
mc ls rustfs/releases/ | awk '{print $NF}' | while read file; do
|
||
LINK=$(mc share download --expire 7d rustfs/releases/$file | grep Share | awk '{print $2}')
|
||
echo "- [$file]($LINK)" >> links.md
|
||
done
|
||
|
||
echo "✅ 链接汇总已保存到 links.md"
|
||
```
|
||
|
||
---
|
||
|
||
## 参考资源
|
||
|
||
- [MinIO Client 完整文档](https://min.io/docs/minio/linux/reference/minio-mc.html)
|
||
- [mc GitHub 仓库](https://github.com/minio/mc)
|
||
- [RustFS 文档](https://docs.rustfs.com)
|
||
- [AWS S3 API 参考](https://docs.aws.amazon.com/s3/)
|
||
|
||
---
|
||
|
||
## 故障排查
|
||
|
||
### 问题 1: mc 命令未找到
|
||
```bash
|
||
# 重新安装
|
||
curl -sSL https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc
|
||
chmod +x /usr/local/bin/mc
|
||
```
|
||
|
||
### 问题 2: 连接失败
|
||
```bash
|
||
# 检查别名配置
|
||
mc alias list
|
||
|
||
# 重新配置
|
||
mc alias set rustfs https://your-server:9000 ACCESS_KEY SECRET_KEY
|
||
|
||
# 测试连接
|
||
mc admin info rustfs
|
||
```
|
||
|
||
### 问题 3: 权限被拒绝
|
||
```bash
|
||
# 检查访问密钥是否正确
|
||
mc admin user info rustfs ACCESS_KEY
|
||
|
||
# 验证 bucket 权限
|
||
mc anonymous get rustfs/bucket/
|
||
```
|
||
|
||
### 问题 4: 临时链接无法访问
|
||
```bash
|
||
# 检查链接是否过期
|
||
# 重新生成链接
|
||
mc share download --expire 1d rustfs/bucket/file.jar
|
||
|
||
# 或设置为公开访问
|
||
mc anonymous set download rustfs/bucket/
|
||
```
|
||
|
||
---
|
||
|
||
**最后更新**: 2025-10-12
|
||
**维护者**: RustFS Team |