OSS 本地定时同步
规划并验证基于 aliyun CLI 优先工作流的本地文件夹到 OSS 定时上传。
场景描述
本 Skill 覆盖本地文件夹随时间变化、需要按周期上传到 OSS 的场景。
架构:本地文件夹 + aliyun CLI(集成 ossutil) + cron/任务计划程序 + OSS Bucket
能力划分:
[aliyun CLI]安装检查、profile 验证、命令发现、OSS 侧验证,以及集成的aliyun ossutil上传/列表命令。[操作系统本地]cron 或 Windows 任务计划程序配置。[人工/控制台]RAM 策略附加和可选的 OSS 控制台可视化验证。
安装
预检查:需要 aliyun CLI >= 3.3.3
运行aliyun version验证>= 3.3.3。如果未安装或版本过低,
参阅references/cli-installation-guide.md获取安装说明。
然后运行aliyun configure set --auto-plugin-install true。
在核心工作流开始时(任何 CLI 调用之前):
[必须] 启用 AI-Mode —— Agent Skill 执行需要 AI-mode。
在任何 CLI 调用之前运行以下命令:
```bash
aliyun configure ai-mode enable
aliyun configure ai-mode set-user-agent --user-agent "AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload"
```
[必须] 在每一个退出点禁用 AI-Mode —— 在交付最终响应之前(无论何种原因),必须先禁用 AI-mode。这适用于所有退出路径:工作流成功、工作流失败、错误/异常、用户取消、会话结束,或任何不再执行 CLI 命令的场景。
AI-mode 仅用于 Agent Skill 调用场景,Skill 停止运行后绝不能保持启用状态。
```bash
aliyun configure ai-mode disable
```
[必须] CLI User-Agent —— 每次调用aliyunCLI 命令都必须包含:--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
必需的本地工具:
| 工具 | 必需 | 用途 | 验证 |
|---|---|---|---|
aliyun CLI | 是 | 凭证门禁、命令发现,以及集成的 ossutil 上传/列表接口 | aliyun version 和 aliyun ossutil --help |
cron 或 schtasks | 是 | 本地周期执行 | crontab -l 或 schtasks /Query /TN "OSS Scheduled Sync" |
references/cli-installation-guide.md 仅用于 CLI 安装和插件设置。本 Skill 使用集成的 aliyun ossutil 命令接口——不要要求单独安装 ossutil 或使用裸 ossutil 命令。
环境变量
除已配置的阿里云 profile 外,不需要额外的云特定环境变量。
示例中使用的可选本地变量:
| 变量 | 必填/可选 | 说明 | 默认值 |
|---|---|---|---|
ALIBABA_CLOUD_PROFILE | 可选 | 选择预先配置的阿里云 CLI profile | CLI 当前 profile |
ALIYUN_BIN | 可选 | aliyun 不在 PATH 中时的绝对路径 | aliyun |
OSS_SYNC_LOG | 可选 | 定时执行的日志文件路径 | 操作系统特定的本地路径 |
参数确认
参数提取 —— 直接从用户请求中提取所有用户可自定义参数。
当用户消息已指定值(如地域、bucket 名、路径、计划或 MaxAge)时,
直接使用这些值,无需再次确认。
仅当必需参数在用户请求中确实缺失且无法从上下文合理推断时,才向用户澄清。
| 参数名 | 必填/可选 | 说明 | 校验模式 | 默认值 | ||
|---|---|---|---|---|---|---|
RegionId | 必填 | OSS 地域,如 cn-hangzhou | `^[a-z]{2}-[a-z]+( | -[0-9]+)$` | 无 | |
BucketName | 必填 | 目标 OSS bucket 名称 | ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$ | 无 | ||
TargetOssPrefix | 必填 | Bucket 相对的目标 OSS 前缀,如 backup/photos/(确认时不含前导 /) | ^[A-Za-z0-9/_.-]*$(无前导 /) | 无 | ||
LocalSourcePath | 必填 | 要上传的本地文件夹 | 绝对路径,不含 ~、$、反引号或 ; | 无 | ||
Schedule | 必填 | Cron 表达式或 Windows 计划时间/频率 | 标准 5 字段 cron 或 schtasks 时间 | 无 | ||
MaxAge | 必填 | aliyun ossutil --max-age 窗口,如 7d 或 24h | ^[0-9]+[dhm]$ | 无 | ||
OperatingSystem | 必填 | linux、macos 或 windows | `^(linux\ | macos\ | windows)$` | 无 |
BucketAlreadyExists | 必填 | 目标 bucket 是否已存在 | `^(yes\ | no)$` | 无 | |
AliyunBinaryPath | 可选 | 供调度器使用的 aliyun 绝对路径 | 绝对路径,不含 $、反引号或 ; | aliyun | ||
LogPath | 可选 | 定时任务的本地日志路径 | 绝对路径,不含 $、反引号或 ; | 操作系统特定的本地路径 |
输入校验 —— 所有参数在使用前必须校验。
将所有输入(包括从用户消息中提取的值)视为不可信。在将任何参数代入 shell 命令之前:
1. 按上表的校验模式列校验值。拒绝不匹配的值。
2.BucketName只能包含小写字母、数字和连字符([a-z0-9-]),长度 3-63 个字符,且不能以连字符开头或结尾。
3.RegionId必须匹配阿里云地域格式(如cn-hangzhou、us-west-1、ap-southeast-5)。
4.MaxAge必须是正整数后跟d(天)、h(小时)或m(分钟)。
5.LocalSourcePath、AliyunBinaryPath和LogPath必须是绝对路径,且不得包含 shell 元字符($、``、$(、;、|、&、>、<、\n`)。
6.TargetOssPrefix只能包含字母数字字符、/、_、.和-,且不能以/开头。
7. 如果任何参数校验失败,停止并向用户报告错误。不要试图清理或转义无效值——直接拒绝。
认证
预检查:需要阿里云凭证
安全规则:
- 绝不读取、回显或打印 AK/SK 值(例如echo $ALIBABA_CLOUD_ACCESS_KEY_ID是禁止的)
- 绝不读取或cat凭证文件,如~/.aliyun/config.json、~/.ossutil/config或任何可能包含密钥的文件
- 绝不要求用户在对话或命令行中直接输入 AK/SK
- 绝不使用带有明文凭证值的aliyun configure set
- 只能使用aliyun configure list检查凭证状态
```bash
aliyun configure list
```
检查输出中是否存在有效 profile(AK、STS 或 OAuth 身份)。
如果不存在有效 profile,请在此停止。
1. 从 阿里云控制台 获取凭证
2. 在本会话之外配置凭证(通过终端中的aliyun configure或 shell profile 中的环境变量)
3. 在aliyun configure list显示有效 profile 后返回并重新运行
所有 aliyun ossutil 命令复用当前活动的 CLI profile。不要打印或硬编码密钥。不要用 ossutil config 或任何其他密钥输入流程替换此门禁。
RAM 策略
默认工作流需要最小权限访问,用于 bucket 发现、bucket 元数据验证,以及在已确认前缀下的对象上传。
| 范围 | 所需操作 |
|---|---|
| 账户级验证 | oss:ListBuckets |
| 目标 bucket 验证 | oss:GetBucketInfo |
| 目标前缀下的增量上传 | oss:PutObject、oss:GetObject、oss:ListObjects |
| 可选测试清理 | oss:DeleteObject |
使用 references/ram-policies.md 获取策略 JSON 和前缀限定资源示例。
不要围绕 oss:AbortMultipartUpload 重新定义默认最小权限集。在本 Skill 中,默认最小权限路径锚定在 bucket 发现、bucket 元数据验证和前缀限定的上传/列表/读取操作上。多部分上传清理权限仅在用户明确要求时才作为后续工作。
核心工作流
执行,而非仅记录。 在环境中直接运行每个步骤的命令。不要只写解决方案文档或脚本——实际对真实环境执行aliyun version、aliyun configure list、aliyun ossutil cp等。
从用户请求中提取RegionId、BucketName、TargetOssPrefix、LocalSourcePath、Schedule、MaxAge、OperatingSystem和BucketAlreadyExists。仅当必需参数确实缺失时才询问用户。
步骤 1:验证 CLI 和凭证 [aliyun CLI]
aliyun version
aliyun configure list
aliyun configure ai-mode enable
验证:
aliyun版本>= 3.3.3- 至少存在一个有效 profile
- AI 安全模式已启用(危险操作将被阻止)
如果版本过低或 aliyun 缺失,参阅 references/cli-installation-guide.md。不要通过改用独立 ossutil 或 aliyun ossutil sync 来绕过缺失的 CLI。
步骤 2:验证或创建 bucket 前置条件 [aliyun CLI]
始终从检查候选 bucket 清单开始:
aliyun ossutil api list-buckets --output-format json \
--read-timeout 60 --connect-timeout 30 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
如果 BucketAlreadyExists=yes,显式验证所选 bucket:
aliyun ossutil stat "oss://${BucketName}" --region "${RegionId}" --output-format json \
--read-timeout 60 --connect-timeout 30 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
跨地域注意事项:当活动 CLI profile 的地域(由aliyun configure list显示)与目标 bucket 的RegionId不同时,你必须在stat、ls和cp命令上添加--region "${RegionId}"。仅用--endpoint不够,因为请求签名地域也必须匹配。--regionflag 一步同时覆盖 endpoint 和签名地域。
需要确认:
- bucket 名称存在于账户清单中
- bucket 地域与
RegionId匹配 - bucket 可通过活动 profile 访问
- 如果多个现有 bucket 都能满足同一备份目标,可以提醒用户启用版本控制的 bucket 更适合备份安全,但这只是建议,不阻止使用已确认的现有 bucket
如果 BucketAlreadyExists=no,使用先检查后操作的幂等模式:
- 先运行
list-buckets(上方)确认 bucket 在账户中确实不存在——如果已存在,跳过创建直接进入stat验证。 - 仅当确认 bucket 不存在时,按本 Skill 现有创建流程创建它。
- 创建后,立即重新运行
stat验证:
aliyun ossutil stat "oss://${BucketName}" --region "${RegionId}" --output-format json \
--read-timeout 60 --connect-timeout 30 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
周期性备份场景的可选建议:
- 如果存在多个候选 bucket 且其中一个已启用版本控制,提及它更适合备份回滚安全
- 如果已确认的现有 bucket 未启用版本控制,仍可用于本工作流;启用版本控制只是可选加固建议,不是前置条件
保持 aliyun ossutil 作为上传和验证命令(如 cp、ls、stat)的规范接口。对于 bucket 创建,遵循本 Skill 已记录的现有创建流程,而非在此发明新的命令族。不要为了掩盖缺失的前置条件而伪造成功、额外部署文件或假的本地产物。
步骤 3:运行规范的增量上传测试 [aliyun CLI / 集成 ossutil]
通过 aliyun ossutil 使用官方数据面命令族执行实际定时上传任务:
aliyun ossutil cp "${LocalSourcePath}" "oss://${BucketName}/${TargetOssPrefix}" \
-r -u \
--max-age "${MaxAge}" \
--region "${RegionId}" \
--read-timeout 300 --connect-timeout 30 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
此命令的关键规则:
-u是强制的:仅当目标对象缺失或源文件比现有 OSS 对象新时才上传-r -u --max-age必须作为规范 flag 集一起使用--region "${RegionId}"确保 endpoint 和签名地域都正确--read-timeout 300 --connect-timeout 30防止命令无限挂起;对非常大的文件可向上调整--read-timeout- 仅为无人值守运行(cron、任务计划程序、CI)添加
-f LocalSourcePath使用绝对路径(绝不使用~)- 规范化
TargetOssPrefix,不含前导/ - 不要用裸
ossutil、aliyun ossutil sync或Cache-Control元数据重写替代
如果 TargetOssPrefix 为空,使用 oss://${BucketName}/(带尾随斜杠)。否则在规范化前缀后使用 oss://${BucketName}/${TargetOssPrefix}。
如果LocalSourcePath在当前环境中不存在(例如容器或 CI runner),在当前工作目录下创建它并放一个小测试文件,然后对其运行上传命令并用aliyun ossutil ls验证。这证明上传路径端到端可用。不要仅因目录缺失就跳过上传测试——创建它并验证连通性、权限和命令正确性:
```bash
mkdir -p "${LocalSourcePath}" && echo "test" > "${LocalSourcePath}/test.txt"
aliyun ossutil cp "${LocalSourcePath}" "oss://${BucketName}/${TargetOssPrefix}" \
-r -u --max-age "${MaxAge}" --region "${RegionId}" \
--read-timeout 300 --connect-timeout 30 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
aliyun ossutil ls "oss://${BucketName}/${TargetOssPrefix}" --region "${RegionId}" \
--read-timeout 60 --connect-timeout 30 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
```
步骤 4:将上传包装为本地脚本 [aliyun CLI + 操作系统本地]
最简脚本模板:
#!/usr/bin/env bash
set -euo pipefail
ALIYUN_BIN="${ALIYUN_BIN:-aliyun}"
LOCAL_SOURCE_PATH="${LocalSourcePath}" # 必须是绝对路径,绝不使用 ~
BUCKET_NAME="${BucketName}"
TARGET_OSS_PREFIX="${TargetOssPrefix#/}"
MAX_AGE="${MaxAge}"
REGION_ID="${RegionId}"
LOG_FILE="${OSS_SYNC_LOG:-$HOME/oss-sync.log}"
READ_TIMEOUT="${READ_TIMEOUT:-600}"
CONNECT_TIMEOUT="${CONNECT_TIMEOUT:-30}"
--- 输入校验 ---
[[ "${BUCKET_NAME}" =~ ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$ ]] || { echo "ERROR: Invalid BucketName: ${BUCKET_NAME}" >&2; exit 1; }
[[ "${REGION_ID}" =~ ^[a-z]{2}-[a-z]+(|-[0-9]+)$ ]] || { echo "ERROR: Invalid RegionId: ${REGION_ID}" >&2; exit 1; }
[[ "${MAX_AGE}" =~ ^[0-9]+[dhm]$ ]] || { echo "ERROR: Invalid MaxAge: ${MAX_AGE}" >&2; exit 1; }
[[ "${TARGET_OSS_PREFIX}" =~ ^[A-Za-z0-9/_.-]*$ ]] || { echo "ERROR: Invalid TargetOssPrefix: ${TARGET_OSS_PREFIX}" >&2; exit 1; }
[[ "${LOCAL_SOURCE_PATH}" == /* ]] || { echo "ERROR: LocalSourcePath must be absolute: ${LOCAL_SOURCE_PATH}" >&2; exit 1; }
TARGET_URI="oss://${BUCKET_NAME}/"
if [ -n "${TARGET_OSS_PREFIX}" ]; then
TARGET_URI="oss://${BUCKET_NAME}/${TARGET_OSS_PREFIX}"
fi
"${ALIYUN_BIN}" ossutil cp "${LOCAL_SOURCE_PATH}" "${TARGET_URI}" \
-r -u -f \
--max-age "${MAX_AGE}" \
--region "${REGION_ID}" \
--read-timeout "${READ_TIMEOUT}" --connect-timeout "${CONNECT_TIMEOUT}" \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload >> "${LOG_FILE}" 2>&1
> **注意**:脚本模板中包含 `-f` flag,因为脚本面向无人值守的 cron/任务计划程序执行,交互式提示不能阻塞任务。`--region` flag 优于 `--endpoint`,因为它同时正确设置 endpoint 和签名地域,这在 CLI profile 默认地域与目标 bucket 地域不同时是必需的。
### 步骤 5:配置调度器 `[操作系统本地]`
**Linux/macOS cron**:
对于本 Skill 中默认的 Linux/macOS 路径,保持 `cron` / `crontab` 作为记录的调度器接口。**不要**在用户未明确要求 launchd 特定变体时静默把答案换成 `launchd`。
> **如果 `crontab` 未找到**:在容器或最小环境中,`crontab` 可能未预装。先安装 `cronie` 包:
> - CentOS/阿里云 Linux/RHEL:`yum install -y cronie`
> - Debian/Ubuntu:`apt-get install -y cron`
>
> 如果 `systemctl start crond` 失败(例如容器中无 systemd),仍可通过 `crontab` 添加 cron 条目——cron 守护进程对条目注册并非严格必需,只对实际执行必需。此类情况下,把 cron 条目记录给用户在其生产主机上部署,**不要**让缺失的守护进程阻塞工作流其余部分。
crontab -e
示例条目(用 `echo ... | crontab -` 进行非交互式安装):
0 3 * * * /usr/local/bin/oss-sync-upload.sh >> /var/log/oss-sync-cron.log 2>&1
**Windows 任务计划程序**通过本地 CLI:
schtasks /Create /SC DAILY /ST 03:00 /TN "OSS Scheduled Sync" /TR "C:\tools\oss-sync-upload.bat"
明确将此步骤标记为操作系统本地。它不是阿里云 API 操作。保持调度器输出最小且可直接操作;除非用户明确要求,否则不要把这步膨胀成额外的 README 文件、XML 导出、PowerShell 包装器、演示负载或其他辅助产物。
### 步骤 6:验证上传目标 `[aliyun CLI / 集成 ossutil]`
任何上传后(包括步骤 3 的测试上传)始终运行此验证:
aliyun ossutil ls "oss://${BucketName}/${TargetOssPrefix}" --region "${RegionId}" \
--read-timeout 60 --connect-timeout 30 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
确认预期对象出现在目标前缀下。**不要**跳过此步骤——它证明端到端连通性和权限。
如果用户想要人工目视检查,明确标记为 `[人工/控制台]` 并在 OSS 控制台确认目标前缀。
### 步骤 7:清晰说明能力边界
相关时始终说明这些限制:
- **实际增量同步步骤通过 `aliyun ossutil` 运行。** 本 Skill 保持在 `aliyun` CLI 接口上,不要求单独安装独立 ossutil。
- **调度器设置是操作系统本地的。** Cron 和任务计划程序在主机操作系统上配置,而非通过阿里云 API。
- **RAM 策略附加通常人工完成或遵循用户现有 IAM 工作流。**
- **目标 bucket 缺失时,应在定时上传前创建 bucket。** 该前置条件遵循本 Skill 现有创建流程。
- **如果有多个等价现有 bucket 可用,可以提醒用户启用版本控制的 bucket 更适合备份安全。** 如果没有版本控制 bucket,继续使用已确认的现有 bucket,不要阻塞工作流。
- **可选 OSS 控制台检查为人工操作。**
- **不要模拟成功。** 前置条件缺失时如实说明,而非创建假的本地测试数据、假装执行日志或额外打包产物。
成功验证方法
以 references/verification-method.md 作为权威检查清单。
最低通过条件:
aliyun configure list显示有效 profile。aliyun ossutil cp --help成功。- 规范的
aliyun ossutil cp ... -r -u --max-age ... --region ...命令完成且无权限或 endpoint 错误。 aliyun ossutil ls ... --region ...在已确认前缀下显示预期上传对象。- 上传命令保留
-u,意味着仅当目标对象缺失或本地源文件比现有 OSS 对象新时才上传。 - 本地调度器条目通过
crontab -l或任务计划程序历史/查询可见,或当当前环境无 crontab 时记录给用户。
清理
清理是可选的,因为本 Skill 面向周期性同步,但测试产物和调度器条目可安全移除。
Linux/macOS cron [操作系统本地]:
- 用
crontab -e移除 cron 行 - 仅当用户明确想要回滚时删除本地脚本和日志文件
Windows 任务计划程序 [操作系统本地]:
schtasks /Delete /TN "OSS Scheduled Sync" /F
可选 OSS 测试清理 [aliyun CLI / 集成 ossutil]:
aliyun ossutil rm "oss://${BucketName}/${TargetOssPrefix}test-object.txt" --region "${RegionId}" \
--read-timeout 60 --connect-timeout 30 \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload
除非用户明确要求该清理范围,否则不要删除 bucket 或生产对象。
禁用 AI 安全模式 [aliyun CLI]:
所有任务完成后,禁用 AI 安全模式以恢复正常 CLI 行为:
aliyun configure ai-mode disable
API 与命令表
参见 references/related-apis.md 获取命令清单、OSS 能力说明和验证说明。该文件仅为参考元数据。
最佳实践
- 保持
aliyun用于预检查、命令发现、bucket 验证,集成aliyun ossutil cp用于实际定时上传。 - 在所有
aliyun ossutil命令(stat、cp、ls、rm)上使用--region "${RegionId}"确保 endpoint 和签名地域都正确。当 CLI profile 默认地域与目标 bucket 地域不同时尤其重要。不要仅依赖--endpoint,因为它不覆盖签名地域,跨地域使用 STS token 时会失败并报“Invalid signing region in Authorization header”错误。 - 保持调度器步骤标记为操作系统本地,让用户理解它们在阿里云 API 之外。
- 使用尽可能窄的 RAM 策略:账户级 bucket 清单、目标 bucket 上的 bucket info、仅在已确认前缀上的对象上传。
- 在真实执行前,在目标机器上运行
aliyun version和aliyun configure list。 - 绝不打印 AK/SK 值,绝不在脚本中硬编码,绝不读取
~/.aliyun/config.json等凭证文件,绝不用内联密钥处理替换凭证门禁。 - 如果 bucket 不存在,先创建再配置定时上传。如果多个现有 bucket 都能满足同一备份目标,可以提醒用户启用版本控制的 bucket 更适合备份安全,但如果没有此类 bucket,继续使用已确认的现有 bucket。
- 命令和脚本中始终对
LocalSourcePath使用绝对路径。不要使用~(波浪号),因为它可能在引号字符串内不展开,导致“not a directory”错误。 - 面向 cron 或任务计划程序生成的脚本中,包含
-fflag 以防止交互式确认提示阻塞无人值守执行。
参考链接
| 参考文档 | 说明 |
|---|---|
references/cli-installation-guide.md | 从 creator skill 资产复制的必需 CLI 安装指南 |
references/verification-method.md | 预检查、上传、调度器和人工验证清单 |
references/related-apis.md | aliyun 和集成 ossutil 命令清单及 OSS API 映射 |
references/ram-policies.md | 验证和上传的最小权限 RAM 策略指导 |
references/acceptance-criteria.md | 本场景的正确和错误命令模式 |
阿里云skills
◯ 评论 0