OSS 定时本地同步
使用阿里云 CLI 优先的工作流,规划并验证从本地文件夹到 OSS 的定时上传。
场景说明
此 skill 适用于本地文件夹会随时间变化且必须定期上传到 OSS 的场景。
架构:Local folder + aliyun CLI (integrated ossutil) + cron/Task Scheduler + OSS Bucket
能力划分:
[aliyun CLI]安装检查、配置文件验证、命令发现、OSS 端验证,以及集成的aliyun ossutil上传/列出命令。[OS-local]cron 或 Windows 任务计划程序配置。[Manual/Console]附加 RAM 策略,以及选择性地在 OSS 控制台中进行可视化验证。
安装
预检查:强制要求阿里云 CLI >= 3.3.3
运行aliyun version,验证版本是否满足>= 3.3.3的要求。如果尚未安装或版本过低,
请参阅 references/cli-installation-guide.md 获取安装说明。
然后运行 aliyun configure set --auto-plugin-install true。
在核心工作流开始时(调用任何 CLI 之前):
[必须] 启用 AI-Mode——AI-mode 是执行 Agent Skill 的强制要求。
调用任何 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——每次调用 aliyun CLI 命令时都必须包含:
--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 命令。
环境变量
除了已配置的阿里云配置文件外,不需要任何额外的云服务专用环境变量。
示例中使用的可选本地变量:
| 变量 | 必填/可选 | 说明 | 默认值 | | --- | --- | --- | --- | | ALIBABA_CLOUD_PROFILE | 可选 | 选择预先配置的阿里云 CLI 配置文件 | CLI 当前配置文件 | | ALIYUN_BIN | 可选 | 当 aliyun 尚未加入 PATH 时,其绝对路径 | aliyun | | OSS_SYNC_LOG | 可选 | 定时执行的日志文件路径 | 特定于 OS 的本地路径 |
参数确认
参数提取——直接从用户请求中提取所有可由用户自定义的参数。
当用户消息已指定具体值(例如地域、存储桶名称、路径、计划或 MaxAge)时,
直接使用这些值,无需再次确认。
仅当用户请求中确实缺少某个必需参数
且无法根据上下文合理推断时,才向用户询问以澄清。
| 参数名称 | 必填/可选 | 说明 | 验证模式 | 默认值 | | --- | --- | --- | --- | --- | | RegionId | 必需 | OSS 地域,例如 cn-hangzhou | ^[a-z]{2}-[a-z]+(|-[0-9]+)$ | 无 | | BucketName | 必填 | 目标 OSS 存储桶名称 | ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$ | 无 | | TargetOssPrefix | 必填 | 相对于存储桶的目标 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 | 必填 | 目标存储桶是否已存在 | ^(yes|no)$ | 无 | | AliyunBinaryPath | 可选 | 供调度器使用的 aliyun 绝对路径 | 绝对路径,不得包含 $、反引号或 ; | aliyun | | LogPath | 可选 | 计划任务的本地日志路径 | 绝对路径,不得包含 $、反引号或 ; | 特定于 OS 的本地路径 |
输入验证——所有参数在使用前都必须经过验证。
将所有输入(包括从用户消息中提取的值)视为不可信。在将任何参数代入 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
```
检查输出中是否存在有效的配置文件(AK、STS 或 OAuth 身份)。
如果不存在有效的配置文件,必须在此处停止。
1. 从 阿里云控制台 获取凭据
2. 在此会话之外配置凭据(在终端中使用 aliyun configure,或使用 shell 配置文件中的环境变量)
3. 待 aliyun configure list 显示有效的配置文件后,返回并重新运行
对所有 aliyun ossutil 命令复用当前启用的 CLI 配置文件。不得打印或硬编码机密信息。不得使用 ossutil config 或任何其他机密信息输入流程取代此检查环节。
RAM 策略
默认工作流需要拥有用于发现存储桶、验证存储桶元数据以及在已确认前缀下上传对象的最小权限。
| 范围 | 必需操作 | | --- | --- | | 账号级验证 | oss:ListBuckets | | 目标存储桶验证 | oss:GetBucketInfo | | 增量上传到目标前缀 | oss:PutObject, oss:GetObject, oss:ListObjects | | 可选的测试清理 | oss:DeleteObject |
有关策略 JSON 和限定于前缀范围的资源示例,请参阅 references/ram-policies.md。
不得以 oss:AbortMultipartUpload 为核心重新定义默认最小权限集。在此 skill 中,默认最小权限路径仍以存储桶发现、存储桶元数据验证以及限定于前缀范围的上传、列举和读取操作为基础。只有当用户明确要求时,才将分片上传清理权限作为后续工作处理。
核心工作流
实际执行,不得只写文档。 直接在环境中运行每个步骤的命令。不得只编写解决方案文档或脚本,而要在实际环境中真正执行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- 至少存在一个有效配置文件
- AI 安全模式已启用(危险操作将被阻止)
如果版本过低或缺少 aliyun,请参阅 references/cli-installation-guide.md。不得通过改用独立版 ossutil 或 aliyun ossutil sync 来绕过缺少 CLI 的问题。
步骤 2:验证或创建存储桶前置条件 [aliyun CLI]
必须始终先检查候选存储桶清单:
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,请明确验证所选存储桶:
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 配置文件的区域(由aliyun configure list显示)与目标存储桶的RegionId不同,则必须在stat、ls和cp命令中添加--region "${RegionId}"。仅使用--endpoint并不足够,因为请求签名区域也必须匹配。--region标志可一次性覆盖端点和签名区域。
需要确认:
- 账户资源清单中存在该存储桶名称
- 存储桶区域与
RegionId匹配 - 可以使用当前配置文件访问该存储桶
- 如果多个现有存储桶都可满足同一备份目标,可以提醒用户,启用了版本控制的存储桶更有利于保障备份安全;但这只是一项建议,不会阻止使用已确认的现有存储桶
如果 BucketAlreadyExists=no,请使用先检查后操作的幂等模式:
- 首先运行上面的
list-buckets,确认该存储桶确实不存在于账户中——如果已经存在,则跳过创建,直接进行stat验证。 - 仅当确认存储桶不存在时,才按照此 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
定期备份场景的可选建议:
- 如果存在多个候选存储桶,并且其中一个已启用版本控制,请说明该存储桶更有利于保障备份回滚安全
- 如果已确认的现有存储桶未启用版本控制,仍可用于此工作流;启用版本控制只是一项可选的加固建议,并非前置条件
将 aliyun ossutil 作为 cp、ls 和 stat 等上传与验证命令的标准操作入口。创建存储桶时,应遵循此 skill 中已有文档记录的创建流程,而不是在此凭空引入新的命令系列。不得为了掩盖缺失的前置条件而伪造成功结果、额外部署文件或虚假的本地制品。
步骤 3:运行标准增量上传测试 [aliyun CLI / integrated 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必须始终一起使用,作为标准标志组合--region "${RegionId}"可确保端点和签名区域均正确--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 运行器),请在当前工作目录下创建该目录并放入一个小型测试文件,然后对其运行上传命令,并使用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 + OS-local]
最小脚本模板:
#!/usr/bin/env bash
set -euo pipefail
ALIYUN_BIN="${ALIYUN_BIN:-aliyun}"
LOCAL_SOURCE_PATH="${LocalSourcePath}" # MUST be an absolute path, never use ~
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}"
# --- Input validation ---
[[ "${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标志,因为该脚本用于无人值守的 cron 或任务计划程序执行,在这类执行中,交互式提示不得阻塞任务。相较于--endpoint,优先使用--region标志,因为它能正确设置端点和签名区域;当 CLI 配置文件的默认区域与目标存储桶区域不同时,这是必需的。
步骤 5:配置调度器 [OS-local]
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"
将此步骤明确标记为 OS 本地操作。它不是一项阿里云 API 操作。计划任务相关输出应精简且可直接操作;除非用户明确要求,否则不要让此步骤衍生出额外的 README 文件、XML 导出文件、PowerShell 封装脚本、演示载荷或其他辅助产物。
步骤 6:验证上传目标 [aliyun CLI / integrated 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
确认预期对象出现在目标前缀下。不得跳过此步骤——此步骤可验证端到端连通性和权限。
如果用户希望进行手动可视化检查,请将其明确标记为 [Manual/Console],并在 OSS 控制台中确认目标前缀。
步骤 7:明确说明能力边界
适用时,必须始终说明以下限制:
- 实际的增量同步步骤通过
aliyun ossutil执行。 此 skill 始终使用aliyunCLI 命令界面,无需另外安装独立版ossutil。 - 计划任务设置属于 OS 本地操作。 Cron 和任务计划程序在主机 OS 上配置,而不是通过阿里云 APIs 配置。
- RAM 策略的附加通常需手动完成,或遵循用户现有的 IAM 工作流。
- 缺少目标存储桶时,应在定时上传前创建存储桶。 对于此前提条件,请遵循此 skill 中已有的创建流程。
- 如果有多个等效的现有存储桶,可以提醒用户,为确保备份安全,启用版本控制的存储桶更合适。 如果没有已启用版本控制的存储桶,请继续使用已确认的现有存储桶,而不要阻塞工作流。
- 可选的 OSS 控制台检查需手动完成。
- 不得模拟成功。 缺少前提条件时,应明确说明,而不是创建虚假的本地测试数据、伪造的执行日志或额外的打包产物。
成功验证方法
使用 references/verification-method.md 作为权威检查清单。
最低通过条件:
aliyun configure list显示有效的配置文件。aliyun ossutil cp --help执行成功。- 规范的
aliyun ossutil cp ... -r -u --max-age ... --region ...命令执行完成,且未出现权限或端点错误。 aliyun ossutil ls ... --region ...显示已确认前缀下预期的已上传对象。- 上传命令保留
-u,即仅当目标对象不存在或本地源文件比现有 OSS 对象更新时才上传。 - 可通过
crontab -l或任务计划程序的历史记录/查询结果看到本地计划任务条目;如果当前环境中没有 crontab,则已为用户记录该条目。
清理
由于此 skill 用于周期性同步,清理是可选操作,但可以安全删除测试产物和计划任务条目。
Linux/macOS cron 定时任务 [OS-local]:
- 使用
crontab -e删除 cron 条目 - 仅当用户明确希望回滚时,才删除本地脚本和日志文件
Windows 任务计划程序 [OS-local]:
schtasks /Delete /TN "OSS Scheduled Sync" /F
可选的 OSS 测试清理 [aliyun CLI / integrated 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
除非用户明确要求相应的清理范围,否则不得删除存储桶或生产对象。
禁用 AI 安全模式 [aliyun CLI]:
所有任务完成后,禁用 AI 安全模式,以恢复 CLI 的正常行为:
aliyun configure ai-mode disable
API 和命令表
有关命令清单、OSS 能力说明和验证说明,请参阅 references/related-apis.md。该文件仅作为参考元数据。
最佳实践
- 将
aliyun用于预检查、命令发现和存储桶验证,并将集成的aliyun ossutil cp用于实际的定时上传。 - 在所有
aliyun ossutil命令(stat、cp、ls、rm)中使用--region "${RegionId}",以确保端点和签名区域均正确。当 CLI 配置文件的默认区域与目标存储桶的区域不同时,这一点尤其重要。不得仅依赖--endpoint,因为它不会覆盖签名区域,并且跨区域使用 STS 令牌时会因“Authorization 标头中的签名区域无效”错误而失败。 - 始终将计划任务步骤标记为 OS 本地操作,让用户了解这些步骤不属于阿里云 APIs 的范畴。
- 尽可能使用范围最小的 RAM 策略:在账户范围内获取存储桶清单、获取目标存储桶信息,并且仅向已确认的前缀上传对象。
- 在目标机器上实际执行前,运行
aliyun version和aliyun configure list。 - 禁止打印 AK/SK 值,禁止在脚本中硬编码这些值,禁止读取
~/.aliyun/config.json等凭证文件,也禁止用内联密钥处理取代凭证检查关卡。 - 如果存储桶不存在,应先创建,再配置定时上传。如果多个现有存储桶均可满足同一备份目标,可以提醒用户,为确保备份安全,启用版本控制的存储桶更合适;但如果不存在此类存储桶,请继续使用已确认的现有存储桶。
- 在命令和脚本中,始终为
LocalSourcePath使用绝对路径。不要使用~(波浪号),因为它在带引号的字符串中可能不会展开,从而导致“不是目录”错误。 - 在为 cron 或任务计划程序生成的脚本中,请加入
-f标志,以防止交互式确认提示阻塞无人值守执行。
参考链接
| 参考资料 | 描述 | | --- | --- | | references/cli-installation-guide.md | 从创作者 skill 资产复制而来的必备 CLI 安装指南 | | references/verification-method.md | 预检查、上传、调度器和手动验证清单 | | references/related-apis.md | aliyun 及集成式 ossutil 的命令清单和 OSS API 映射 | | references/ram-policies.md | 用于验证和上传的最小权限 RAM 策略指南 | | references/acceptance-criteria.md | 此场景的正确和错误命令模式 |