#!/usr/bin/env bash . "$(cd "$(dirname "$0")/.." && pwd)/config/load.sh" # B2 步(在 47 上跑):rsync 生产 dataRoot → 106 # · --numeric-ids 保 uid/gid(否则 106 上文件属主全错 ⇒ 实例 EACCES) # · 排除 dshs.db*(DB 权威源已是 47 的 PG)与 secret.key(凭据主密钥不外扩到 Worker —— R5 最小面) # · ⚠️ 所有 ssh 调用带 -n:脚本本身经 stdin 传入,ssh 若不隔离 stdin 会把**脚本剩余部分**吃掉 set -uo pipefail KEY=/root/.ssh/dshworker_ed25519 DST=root@"$DSH_PEER_PUBLIC_IP" SRC="$DSHS_DATA_ROOT" SSHOPT="-n -i $KEY -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=10" command -v rsync >/dev/null || { dnf -y install rsync >/tmp/dnf-rsync.log 2>&1 && echo " ✓ 47 装上 rsync"; } echo "=== 连通性 + 对端 rsync ===" ssh $SSHOPT "$DST" 'command -v rsync >/dev/null || dnf -y install rsync >/tmp/dnf-rs.log 2>&1; echo " 对端: $(rsync --version | head -1)"' 2>&1 | tail -2 echo "=== 目标端准备 ===" ssh $SSHOPT "$DST" "mkdir -p $DSHS_DATA_ROOT && ls -ld $DSHS_DATA_ROOT" 2>&1 | sed 's/^/ /' echo "=== rsync ===" rsync -a --numeric-ids --stats -e "ssh $SSHOPT" \ --exclude 'dshs.db' --exclude 'dshs.db-shm' --exclude 'dshs.db-wal' --exclude 'secret.key' \ "$SRC/" "$DST:"$DSHS_DATA_ROOT"/" 2>&1 | grep -E "Number of regular files transferred|Total file size|sent [0-9]|total size is" | sed 's/^/ /' echo "=== 目标端核对 ===" ssh $SSHOPT "$DST" 'bash -c " echo \" 顶层: \$(ls "$DSHS_DATA_ROOT" | tr \"\n\" \" \")\" echo \" users 目录数: \$(ls "$DSHS_DATA_ROOT"/users 2>/dev/null | wc -l)\" for d in "$DSHS_DATA_ROOT"/users/*/; do printf \" %-38s uid=%s\n\" \"\$(basename \$d)\" \"\$(stat -c %u \$d)\"; done echo \" bundled-skills: \$(ls "$DSHS_DATA_ROOT"/bundled-skills 2>/dev/null | wc -l) 项\" echo \" business-plugins: \$(ls "$DSHS_DATA_ROOT"/business-plugins 2>/dev/null | wc -l) 项\" echo \" ⛔ 不应存在(dshs.db/secret.key): \$(ls "$DSHS_DATA_ROOT"/dshs.db "$DSHS_DATA_ROOT"/secret.key 2>/dev/null | wc -l) 个(应为 0)\" "' 2>&1