🔄 卡若AI 同步 2026-03-15 12:31 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 11 个

This commit is contained in:
2026-03-15 12:31:09 +08:00
parent 29c62b51d1
commit b59c87fa12
5 changed files with 299 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
# 阿里云 OSS → 公司 NAS 每日定时同步
## 概述
将阿里云 OSS Bucket `kr-cypd`华北2/北京)的全部数据每日自动同步到公司 NASSynology DS1825+ / 192.168.1.201),并生成费用报告。
## 架构
```
┌──────────────────┐ ossutil sync ┌───────────────────────────┐
│ 阿里云 OSS │ ──────────────────────▶ │ Synology DS1825+ │
│ kr-cypd (北京) │ 每天 03:00 │ /volume1/backup/ │
│ │ │ oss_kr-cypd/ │
└──────────────────┘ └───────────────────────────┘
```
## NAS 目录结构
```
/volume1/backup/oss_kr-cypd/
├── data/ ← OSS 文件同步到这里(按原始目录结构)
│ ├── test/
│ │ └── 2026-03/
│ ├── images/
│ └── ...
├── _snapshots/ ← 每日快照(硬链接,不额外占空间)
│ ├── 2026-03-15/
│ ├── 2026-03-16/
│ └── ...
├── _overwritten/ ← 被覆盖文件的备份
├── _logs/ ← 同步日志 + 每日报告
│ ├── sync_2026-03-15.log
│ ├── report_2026-03-15.md
│ └── cron.log
└── _cost_reports/ ← OSS 月度费用报告
└── cost_2026-03.json
```
## 凭证信息
| 项目 | 值 |
|:---|:---|
| AccessKeyId | `LTAI5t7ixwYZBqYc4bFpe5tc` |
| AccessKeySecret | `Bm1JAMT5U2oyaKLqhbtIPojNQWd5YA` |
| RAM 用户 | gameshop |
| OSS Endpoint | `oss-cn-beijing.aliyuncs.com` |
| Bucket | kr-cypd |
## 费用参考
| 月份 | OSS 费用 | 备注 |
|:---|:---|:---|
| 2026-02 | ¥10.32 | 已结算 |
| 2026-03至15日 | ¥4.83 | 进行中 |
费用主要来自:存储费用 + 请求次数 + 外网流出流量。每日同步走内网不产生流量费(需 NAS 与 OSS 在同一地域,或走公网则产生流出费)。
## 一键部署
```bash
cd "01_卡资/金仓_存储备份/群晖NAS管理/脚本/oss_sync"
bash deploy_to_nas.sh
```
该脚本会自动:
1. 在 NAS 上创建目录结构
2. 上传同步脚本
3. 安装 ossutil如未安装
4. 配置 crontab 定时任务(每天 03:00
## 手动执行同步(测试)
SSH 登录 NAS 后:
```bash
bash /volume1/backup/oss_kr-cypd/oss_sync_to_nas.sh
```
## 同步策略
- **增量同步**ossutil sync 只下载新增/修改的文件,不重复下载
- **每日快照**:用硬链接创建当日快照,不额外占磁盘空间
- **被覆盖备份**:远端文件更新时,旧版本自动备份到 `_overwritten/`
- **分类统计**:按 OSS 顶级目录分类统计文件数量和大小
- **费用监控**:每次同步后查询当月 OSS 费用并写入报告
## 备选方案DSM 任务计划器
如果 NAS 不支持 crontab可在 DSM 控制面板 → 任务计划 中手动添加:
1. 控制面板 → 任务计划 → 新增 → 计划的任务 → 用户定义的脚本
2. 常规任务名称「OSS 每日同步」用户「root」
3. 计划:每天 03:00
4. 任务设置 → 用户定义的脚本:
```bash
/bin/bash /volume1/backup/oss_kr-cypd/oss_sync_to_nas.sh
```
5. 勾选「将运行详情以电子邮件发送」(可选)

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# 一键部署 OSS 同步脚本到公司 NASSynology DS1825+
# 使用方式bash deploy_to_nas.sh
set -euo pipefail
NAS_IP="192.168.1.201"
NAS_USER="fnvtk"
NAS_PASS="zhiqun1984"
REMOTE_DIR="/volume1/backup/oss_kr-cypd"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
echo "====== 部署 OSS→NAS 同步脚本 ======"
echo "[1/4] 创建远程目录..."
sshpass -p "${NAS_PASS}" ssh -o StrictHostKeyChecking=no "${NAS_USER}@${NAS_IP}" \
"mkdir -p ${REMOTE_DIR}/_logs ${REMOTE_DIR}/_cost_reports ${REMOTE_DIR}/_snapshots"
echo "[2/4] 上传同步脚本..."
sshpass -p "${NAS_PASS}" scp -o StrictHostKeyChecking=no \
"${SCRIPT_DIR}/oss_sync_to_nas.sh" \
"${NAS_USER}@${NAS_IP}:${REMOTE_DIR}/oss_sync_to_nas.sh"
sshpass -p "${NAS_PASS}" ssh -o StrictHostKeyChecking=no "${NAS_USER}@${NAS_IP}" \
"chmod +x ${REMOTE_DIR}/oss_sync_to_nas.sh"
echo "[3/4] 安装 ossutil如未安装..."
sshpass -p "${NAS_PASS}" ssh -o StrictHostKeyChecking=no "${NAS_USER}@${NAS_IP}" bash <<'REMOTE_INSTALL'
if ! command -v /usr/local/bin/ossutil &>/dev/null; then
echo "正在下载 ossutil..."
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then
URL="https://gosspublic.alicdn.com/ossutil/v2/2.0.3/ossutil-v2.0.3-linux-amd64.zip"
else
URL="https://gosspublic.alicdn.com/ossutil/v2/2.0.3/ossutil-v2.0.3-linux-arm64.zip"
fi
cd /tmp
wget -q "${URL}" -O ossutil.zip
unzip -o ossutil.zip -d ossutil_pkg
cp ossutil_pkg/ossutil*/ossutil /usr/local/bin/ossutil
chmod +x /usr/local/bin/ossutil
rm -rf ossutil.zip ossutil_pkg
echo "ossutil 安装完成: $(/usr/local/bin/ossutil version)"
else
echo "ossutil 已安装: $(/usr/local/bin/ossutil version)"
fi
REMOTE_INSTALL
echo "[4/4] 配置 NAS 定时任务(每天凌晨 03:00..."
CRON_LINE="0 3 * * * /bin/bash ${REMOTE_DIR}/oss_sync_to_nas.sh >> ${REMOTE_DIR}/_logs/cron.log 2>&1"
sshpass -p "${NAS_PASS}" ssh -o StrictHostKeyChecking=no "${NAS_USER}@${NAS_IP}" bash <<REMOTE_CRON
EXISTING=\$(crontab -l 2>/dev/null || true)
if echo "\${EXISTING}" | grep -q "oss_sync_to_nas"; then
echo "定时任务已存在,跳过"
else
(echo "\${EXISTING}"; echo "${CRON_LINE}") | crontab -
echo "定时任务已添加: 每天 03:00"
fi
REMOTE_CRON
echo ""
echo "====== 部署完成 ======"
echo "同步脚本: ${NAS_USER}@${NAS_IP}:${REMOTE_DIR}/oss_sync_to_nas.sh"
echo "备份目录: ${REMOTE_DIR}/data/"
echo "每日快照: ${REMOTE_DIR}/_snapshots/YYYY-MM-DD/"
echo "费用报告: ${REMOTE_DIR}/_cost_reports/"
echo "同步日志: ${REMOTE_DIR}/_logs/"
echo "定时任务: 每天 03:00 自动执行"

View File

@@ -0,0 +1,130 @@
#!/usr/bin/env bash
# OSS Bucket kr-cypd → NAS 每日定时同步脚本
# 部署目标Synology DS1825+CKBNAS / 192.168.1.201
# 计划任务:每天凌晨 03:00
set -euo pipefail
# ──────────────────── 配置区 ────────────────────
OSS_ENDPOINT="oss-cn-beijing.aliyuncs.com"
OSS_BUCKET="kr-cypd"
ACCESS_KEY_ID="LTAI5t7ixwYZBqYc4bFpe5tc"
ACCESS_KEY_SECRET="Bm1JAMT5U2oyaKLqhbtIPojNQWd5YA"
NAS_BACKUP_ROOT="/volume1/backup/oss_kr-cypd"
LOG_DIR="${NAS_BACKUP_ROOT}/_logs"
COST_DIR="${NAS_BACKUP_ROOT}/_cost_reports"
ALIYUN_CLI="/usr/local/bin/aliyun"
OSSUTIL="/usr/local/bin/ossutil"
DATE_TAG=$(date +%Y-%m-%d)
MONTH_TAG=$(date +%Y-%m)
LOG_FILE="${LOG_DIR}/sync_${DATE_TAG}.log"
# ────────────────────────────────────────────────
mkdir -p "${NAS_BACKUP_ROOT}" "${LOG_DIR}" "${COST_DIR}"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "${LOG_FILE}"; }
log "========== OSS 同步开始 =========="
log "Bucket: oss://${OSS_BUCKET}${NAS_BACKUP_ROOT}"
# ──────────────── 1. ossutil 增量同步 ────────────────
SYNC_START=$(date +%s)
"${OSSUTIL}" sync \
"oss://${OSS_BUCKET}/" \
"${NAS_BACKUP_ROOT}/data/" \
--endpoint "${OSS_ENDPOINT}" \
--access-key-id "${ACCESS_KEY_ID}" \
--access-key-secret "${ACCESS_KEY_SECRET}" \
--force \
--backup-dir "${NAS_BACKUP_ROOT}/_overwritten" \
--include "*" \
2>&1 | tee -a "${LOG_FILE}"
SYNC_END=$(date +%s)
SYNC_ELAPSED=$(( SYNC_END - SYNC_START ))
log "同步耗时: ${SYNC_ELAPSED}s"
# ──────────── 2. 按日期归档(硬链接,不额外占空间) ──────────
DAILY_SNAPSHOT="${NAS_BACKUP_ROOT}/_snapshots/${DATE_TAG}"
if [ ! -d "${DAILY_SNAPSHOT}" ]; then
mkdir -p "${DAILY_SNAPSHOT}"
cp -al "${NAS_BACKUP_ROOT}/data/" "${DAILY_SNAPSHOT}/"
log "每日快照已创建: ${DAILY_SNAPSHOT}"
fi
# ──────────── 3. 统计本次同步文件数与大小 ──────────
FILE_COUNT=$(find "${NAS_BACKUP_ROOT}/data/" -type f 2>/dev/null | wc -l | tr -d ' ')
TOTAL_SIZE=$(du -sh "${NAS_BACKUP_ROOT}/data/" 2>/dev/null | cut -f1)
log "当前文件总数: ${FILE_COUNT},总大小: ${TOTAL_SIZE}"
# ──────────── 4. 分类存储统计 ──────────
log "--- 分类存储统计 ---"
for dir in "${NAS_BACKUP_ROOT}/data"/*/; do
[ -d "${dir}" ] || continue
CATEGORY=$(basename "${dir}")
CAT_COUNT=$(find "${dir}" -type f | wc -l | tr -d ' ')
CAT_SIZE=$(du -sh "${dir}" | cut -f1)
log " [${CATEGORY}] 文件数: ${CAT_COUNT}, 大小: ${CAT_SIZE}"
done
# ──────────── 5. OSS 费用查询(本月) ──────────
COST_FILE="${COST_DIR}/cost_${MONTH_TAG}.json"
if command -v "${ALIYUN_CLI}" &>/dev/null; then
log "正在查询 OSS 本月费用..."
"${ALIYUN_CLI}" bssopenapi QueryBill \
--region cn-beijing \
--BillingCycle "${MONTH_TAG}" \
--ProductCode oss \
--access-key-id "${ACCESS_KEY_ID}" \
--access-key-secret "${ACCESS_KEY_SECRET}" \
> "${COST_FILE}" 2>&1 || true
if [ -f "${COST_FILE}" ]; then
AMOUNT=$(python3 -c "
import json, sys
try:
d = json.load(open('${COST_FILE}'))
items = d.get('Data',{}).get('Items',{}).get('Item',[])
total = sum(i.get('PretaxAmount',0) for i in items)
print(f'{total:.2f}')
except: print('N/A')
" 2>/dev/null || echo "N/A")
log "OSS 本月费用: ¥${AMOUNT}"
fi
else
log "aliyun CLI 未安装,跳过费用查询"
fi
# ──────────── 6. 生成每日同步报告 ──────────
REPORT_FILE="${LOG_DIR}/report_${DATE_TAG}.md"
cat > "${REPORT_FILE}" <<REPORT_EOF
# OSS 同步报告 — ${DATE_TAG}
| 项目 | 值 |
|:---|:---|
| Bucket | oss://${OSS_BUCKET} |
| 目标路径 | ${NAS_BACKUP_ROOT}/data/ |
| 同步耗时 | ${SYNC_ELAPSED}s |
| 文件总数 | ${FILE_COUNT} |
| 数据总量 | ${TOTAL_SIZE} |
| 本月 OSS 费用 | ¥${AMOUNT:-N/A} |
## 分类明细
$(for dir in "${NAS_BACKUP_ROOT}/data"/*/; do
[ -d "${dir}" ] || continue
CATEGORY=$(basename "${dir}")
CAT_COUNT=$(find "${dir}" -type f | wc -l | tr -d ' ')
CAT_SIZE=$(du -sh "${dir}" | cut -f1)
echo "- **${CATEGORY}**: ${CAT_COUNT} 个文件, ${CAT_SIZE}"
done)
## 快照
每日快照: \`${DAILY_SNAPSHOT}\`
REPORT_EOF
log "报告已生成: ${REPORT_FILE}"
log "========== OSS 同步完成 =========="

View File

@@ -356,3 +356,4 @@
| 2026-03-14 10:36:14 | 🔄 卡若AI 同步 2026-03-14 10:36 | 更新:水桥平台对接、水溪整理归档、火炬、运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-15 07:05:48 | 🔄 卡若AI 同步 2026-03-15 07:05 | 更新:水桥平台对接、运营中枢、运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-15 07:12:23 | 🔄 卡若AI 同步 2026-03-15 07:12 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-15 07:18:57 | 🔄 卡若AI 同步 2026-03-15 07:18 | 更新:火炬、火种知识模型、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 11 个 |

View File

@@ -359,3 +359,4 @@
| 2026-03-14 10:36:14 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-14 10:36 | 更新:水桥平台对接、水溪整理归档、火炬、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-15 07:05:48 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-15 07:05 | 更新:水桥平台对接、运营中枢、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-15 07:12:23 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-15 07:12 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-15 07:18:57 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-15 07:18 | 更新:火炬、火种知识模型、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |