#!/bin/bash # NAS 端:VPS parquet(static+valuation) 全量 scp pull(一次性备份,非每日)。 # 脱离 ssh 会话运行(避免 sshd 关会话杀进程组): # nohup setsid bash sync_parquet.sh /dev/null 2>&1 & set -u KEY=/var/services/homes/admin/.ssh/id_ed25519_nas VPS=Administrator@49.232.102.198 DATA=/volume1/stock/sanguo_vnpy_v2/data LOG=/volume1/stock/sanguo_vnpy_v2/data_backup/parquet.log # 互斥锁(2026-08-21): 触发源两路=周日钩子(sync_valuation_daily.sh)与 DSM id=6 周日04:00, # 双 scp -r 并发写同文件会撕损; mkdir 原子锁, >6h 视陈旧覆盖(单跑 70min 远不到)。 LOCK=/volume1/stock/sanguo_vnpy_v2/data_backup/parquet_full.lock if [ -d "$LOCK" ]; then if [ -z "$(find "$LOCK" -maxdepth 0 -mmin +360 2>/dev/null)" ]; then echo "[$(date '+%T')] lock held, another full sync running -> skip" >> "$LOG" exit 0 fi rmdir "$LOCK" 2>/dev/null fi mkdir "$LOCK" 2>/dev/null || { echo "[$(date '+%T')] lock mkdir fail" >> "$LOG"; exit 1; } trap 'rmdir "$LOCK" 2>/dev/null' EXIT echo "=== parquet scp start $(date) ===" >> "$LOG" cd "$DATA" || { echo "cd fail" >> "$LOG"; exit 1; } # scp -r 覆盖式拉取(6.24GB 全量约 70min;ServerAliveInterval 保活防跨公网 broken pipe + retry 兜底) SCP_OK=0 for attempt in 1 2 3; do if scp -r -i "$KEY" -o StrictHostKeyChecking=no -o ServerAliveInterval=30 -o ServerAliveCountMax=20 \ "$VPS:C:/sanguo_vnpy_v2/data/static" \ "$VPS:C:/sanguo_vnpy_v2/data/valuation_baostock" \ "$VPS:C:/sanguo_vnpy_v2/data/fundamentals_baostock" ./ >> "$LOG" 2>&1; then SCP_OK=1 break fi echo "[$(date '+%T')] scp attempt $attempt broken pipe, retry..." >> "$LOG" sleep 10 done echo "SCP_RC OK=$SCP_OK $(date)" >> "$LOG" du -sh "$DATA/static" "$DATA/valuation_baostock" "$DATA/fundamentals_baostock" >> "$LOG" 2>&1 echo "PARQUET_DONE $(date)" >> "$LOG"