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 —— 每次调用 aliyun CLI 命令都必须包含:
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-oss-manage-cron-upload

必需的本地工具:

工具必需用途验证
aliyun CLI凭证门禁、命令发现,以及集成的 ossutil 上传/列表接口aliyun versionaliyun ossutil --help
cronschtasks本地周期执行crontab -lschtasks /Query /TN "OSS Scheduled Sync"

references/cli-installation-guide.md 仅用于 CLI 安装和插件设置。本 Skill 使用集成的 aliyun ossutil 命令接口——不要要求单独安装 ossutil 或使用裸 ossutil 命令。

环境变量

除已配置的阿里云 profile 外,不需要额外的云特定环境变量。

示例中使用的可选本地变量:

变量必填/可选说明默认值
ALIBABA_CLOUD_PROFILE可选选择预先配置的阿里云 CLI profileCLI 当前 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 窗口,如 7d24h^[0-9]+[dhm]$
OperatingSystem必填linuxmacoswindows`^(linux\macos\windows)$`
BucketAlreadyExists必填目标 bucket 是否已存在`^(yes\no)$`
AliyunBinaryPath可选供调度器使用的 aliyun 绝对路径绝对路径,不含 $、反引号或 ;aliyun
LogPath可选定时任务的本地日志路径绝对路径,不含 $、反引号或 ;操作系统特定的本地路径
输入校验 —— 所有参数在使用前必须校验。
将所有输入(包括从用户消息中提取的值)视为不可信。在将任何参数代入 shell 命令之前:
1. 按上表的校验模式列校验值。拒绝不匹配的值。
2. BucketName 只能包含小写字母、数字和连字符([a-z0-9-]),长度 3-63 个字符,且不能以连字符开头或结尾。
3. RegionId 必须匹配阿里云地域格式(如 cn-hangzhouus-west-1ap-southeast-5)。
4. MaxAge 必须是正整数后跟 d(天)、h(小时)或 m(分钟)。
5. LocalSourcePathAliyunBinaryPathLogPath 必须是绝对路径,且不得包含 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:PutObjectoss:GetObjectoss:ListObjects
可选测试清理oss:DeleteObject

使用 references/ram-policies.md 获取策略 JSON 和前缀限定资源示例。

不要围绕 oss:AbortMultipartUpload 重新定义默认最小权限集。在本 Skill 中,默认最小权限路径锚定在 bucket 发现、bucket 元数据验证和前缀限定的上传/列表/读取操作上。多部分上传清理权限仅在用户明确要求时才作为后续工作。

核心工作流

执行,而非仅记录。 在环境中直接运行每个步骤的命令。不要只写解决方案文档或脚本——实际对真实环境执行 aliyun versionaliyun configure listaliyun ossutil cp 等。
从用户请求中提取 RegionIdBucketNameTargetOssPrefixLocalSourcePathScheduleMaxAgeOperatingSystemBucketAlreadyExists。仅当必需参数确实缺失时才询问用户。

步骤 1:验证 CLI 和凭证 [aliyun CLI]

aliyun version
aliyun configure list
aliyun configure ai-mode enable

验证:

  • aliyun 版本 &gt;= 3.3.3
  • 至少存在一个有效 profile
  • AI 安全模式已启用(危险操作将被阻止)

如果版本过低或 aliyun 缺失,参阅 references/cli-installation-guide.md。不要通过改用独立 ossutilaliyun 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 不同时,你必须statlscp 命令上添加 --region "${RegionId}"。仅用 --endpoint 不够,因为请求签名地域也必须匹配。--region flag 一步同时覆盖 endpoint 和签名地域。

需要确认:

  • bucket 名称存在于账户清单中
  • bucket 地域与 RegionId 匹配
  • bucket 可通过活动 profile 访问
  • 如果多个现有 bucket 都能满足同一备份目标,可以提醒用户启用版本控制的 bucket 更适合备份安全,但这只是建议,不阻止使用已确认的现有 bucket

如果 BucketAlreadyExists=no,使用先检查后操作的幂等模式:

  1. 先运行 list-buckets(上方)确认 bucket 在账户中确实不存在——如果已存在,跳过创建直接进入 stat 验证。
  2. 仅当确认 bucket 不存在时,按本 Skill 现有创建流程创建它。
  3. 创建后,立即重新运行 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 作为上传和验证命令(如 cplsstat)的规范接口。对于 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,不含前导 /
  • 不要用裸 ossutilaliyun ossutil syncCache-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 作为权威检查清单。

最低通过条件:

  1. aliyun configure list 显示有效 profile。
  2. aliyun ossutil cp --help 成功。
  3. 规范的 aliyun ossutil cp ... -r -u --max-age ... --region ... 命令完成且无权限或 endpoint 错误。
  4. aliyun ossutil ls ... --region ... 在已确认前缀下显示预期上传对象。
  5. 上传命令保留 -u,意味着仅当目标对象缺失或本地源文件比现有 OSS 对象新时才上传。
  6. 本地调度器条目通过 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 能力说明和验证说明。该文件仅为参考元数据。

最佳实践

  1. 保持 aliyun 用于预检查、命令发现、bucket 验证,集成 aliyun ossutil cp 用于实际定时上传。
  2. 在所有 aliyun ossutil 命令(statcplsrm)上使用 --region "${RegionId}" 确保 endpoint 和签名地域都正确。当 CLI profile 默认地域与目标 bucket 地域不同时尤其重要。不要仅依赖 --endpoint,因为它不覆盖签名地域,跨地域使用 STS token 时会失败并报“Invalid signing region in Authorization header”错误。
  3. 保持调度器步骤标记为操作系统本地,让用户理解它们在阿里云 API 之外。
  4. 使用尽可能窄的 RAM 策略:账户级 bucket 清单、目标 bucket 上的 bucket info、仅在已确认前缀上的对象上传。
  5. 在真实执行前,在目标机器上运行 aliyun versionaliyun configure list
  6. 绝不打印 AK/SK 值,绝不在脚本中硬编码,绝不读取 ~/.aliyun/config.json 等凭证文件,绝不用内联密钥处理替换凭证门禁。
  7. 如果 bucket 不存在,先创建再配置定时上传。如果多个现有 bucket 都能满足同一备份目标,可以提醒用户启用版本控制的 bucket 更适合备份安全,但如果没有此类 bucket,继续使用已确认的现有 bucket。
  8. 命令和脚本中始终对 LocalSourcePath 使用绝对路径。不要使用 ~(波浪号),因为它可能在引号字符串内不展开,导致“not a directory”错误。
  9. 面向 cron 或任务计划程序生成的脚本中,包含 -f flag 以防止交互式确认提示阻塞无人值守执行。

参考链接

参考文档说明
references/cli-installation-guide.md从 creator skill 资产复制的必需 CLI 安装指南
references/verification-method.md预检查、上传、调度器和人工验证清单
references/related-apis.mdaliyun 和集成 ossutil 命令清单及 OSS API 映射
references/ram-policies.md验证和上传的最小权限 RAM 策略指导
references/acceptance-criteria.md本场景的正确和错误命令模式

文档 5 / 6:alibabacloud-data-agent-skill