多台 Windows 之间的异地互备(SSH 分卷备份 + 断点续传)

SKILL运维和基础设施
运维和基础设施 未标注权限 许可证不明确
安装这个技能

用于「一台机器的数据,在另一台机器上留一份」的场景。几台 Windows 已用 SSH / 组网工具打通,本技能把它们变成一个互备网:源机自己用系统自带 tar 打包(可免压缩)、切成 GB 级分卷、经 SFTP 推到目标机最空的盘、每卷都在目标机回读字节数比对、传完按 -Keep 轮转旧份并删掉本地临时包。断网中断后重跑会自动回到同一天的归档目录,已传完的卷跳过、传了一半的卷接着传。当你说「异地备份」「机器之间互备」「把这台机器备份到那台」「备份中断了怎么接着传」「sftp 传大文件」时会用到。触发词:异地备份、互备、双向备份、分卷备份、断点续传、sftp put -a、scp pipe Unknown error、stat remote、BackupHub、备份轮转。

一句话选型结论

按资料字段整理

多台 Windows 之间的异地互备(SSH 分卷备份 + 断点续传)是运维和基础设施类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类运维和基础设施 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_878e6d7a/remote-win-backup-mesh
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

运维和基础设施
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_878e6d7a仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验未标注上游最后核验时间 · 数据更新 1791621868
正文体量16.0 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
查服务与日志

按现象定位服务状态与日志线索。

写部署与巡检脚本

把重复的部署、巡检写成脚本。

故障排查

按步骤排查网络、依赖与配置。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在运维和基础设施场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
多台 Windows 之间的异地互备(SSH 分卷备份 + 断点续传)当前 未标注权限 未标注 未标注 未标注 有
Azure 部署 调用外部服务 GitHub 仓库 664.2 万 Codex、Claude、Cursor 有
Azure diagnostics 问题管理 调用外部服务 GitHub 仓库 657.6 万 Codex、Claude、Cursor 有
Azure aigateway 部署 调用外部服务 GitHub 仓库 655.3 万 Codex、Claude、Cursor 有
Azure AI 搜索 调用外部服务 GitHub 仓库 651.4 万 Codex、Claude、Cursor 有
Azure Cloud migrate 部署 调用外部服务 GitHub 仓库 650.7 万 Codex、Claude、Cursor 有

SKILL.md 全文

16.0 KB
模型实际读到的说明书原文,来自技能仓库

多台 Windows 之间的异地互备

> 版本 1.0.0 | 真机验证:多台 Windows 经组网 + OpenSSH 打通,
> 已端到端跑通 7 GB 全量备份(分卷 → 断网中断 → 重跑续传 → 回读校验 → 按天轮转 → 清理本地临时包),
> 也完整执行过一次「全部拆除」。下面每条规则都有实测日志支撑,不是纸上谈兵。

这个技能解决什么问题

工作成果只存在一台机器上是裸奔:机器坏了、系统崩了、被盗了,东西就没了。
但现成的备份工具在几台家庭 / 办公 Windows 之间很难落地——要装服务端、要配共享、走公网还不安全。

这里给的是一条只用 SSH 就能跑通的路:几台机器互为对方的后备,
源机自己打包 → 推到异地机最空的盘 → 回来读一遍确认没传坏 → 按份数轮转。

什么时候用

  • 手上有两台以上 Windows,彼此能 SSH 互通(组网软件、局域网、VPN 都行)
  • 想把某台机器的桌面 / 工程目录定期放到另一台上
  • 数据量在 GB 级,单次传不完、网络会断,需要能续传
  • 不想装任何备份服务端

先填这张机器表

脚本顶部有一张表,按你的实际情况填。<...> 都是填表前的占位符,真跑之前必须换成真值:

$Machines = @(
    [pscustomobject]@{ Alias='<别名A>'; Host='^<机器名A>$'; User='<用户名>'; IP='<IP-A>'; Label='<机器A 说明:性能最好的主力机>'; BackupTo='<别名C>,<别名D>' }
    [pscustomobject]@{ Alias='<别名B>'; Host='^<机器名B>$'; User='<用户名>'; IP='<IP-B>'; Label='<机器B 说明:随身携带的轻薄本>'; BackupTo='<别名A>,<别名C>' }
)
  • Alias:给机器起的短名,只用 ASCII(会进目录名)
  • Host:用正则匹配本机名,脚本拿它「认自己」
  • BackupTo:候选目标机队列,用逗号分隔,哪台连得上就往哪台备
  • 排队先后有讲究:实测往某台低配机传 7 GB 跑满 60 分钟还被挤断(约 2 MB/s),
    那机器的 CPU 撑不动加密;性能好的机器吞吐明显更好,排前面,长开机的排后面兜底。

⚠️ 同处一个局域网时,主机名会被解析成 IPv6 链路本地地址,脚本里目标一律写 IP。


五条硬规则(不照做必然踩坑)

1. scp / sftp 要用 MSYS2 版

部分机器上的 Win32-OpenSSH 那套(C:\Windows\System32\OpenSSH\scp.exe)会报:

pipe: Unknown error            # 实际是 ERROR_PIPE_BUSY

看着像在传,其实没传成。改用带 MSYS2 运行时的那份(Git for Windows / GitFull / PortableGit 里都有):

<安装目录>\usr\bin\scp.exe
<安装目录>\usr\bin\sftp.exe

打包用系统自带的 bsdtar:C:\Windows\System32\tar.exe(原生支持中文路径和 Windows 盘符)。

2. sftp 的 batch 里,两边路径各说各的行话

batch 文件里要这样写:

put "/c/Users/<用户名>/xxx.tar" "/D:/BackupHub/<别名>/<日期>/xxx.tar"
  • 本地路径必须是 POSIX 形式 /c/Users/...。写 C:\Users\... 的话反斜杠会被 sftp
    当转义字符吃掉,变成 C:UsersADMINI~1AppDataLocalTemp...,报错:
    stat C:UsersADMINI~1...: No such file or directory。
  • 远端路径必须带前导斜杠 /D:/...。写成 D:/xxx 会被当成相对路径,接到用户主目录底下。

转换函数:

function To-Posix([string] $p) {
    $q = $p -replace '\\', '/'
    if ($q -cmatch '^([A-Za-z]):/(.*)$') { $q = '/' + $Matches[1].ToLower() + '/' + $Matches[2] }
    return $q
}

3. put -a(续传)只用于「接着传」,不能用于「开个头」

对着不存在的远端文件用 -a:

sftp> put -a "/c/.../x.tar" "/D:/.../x.tar"
stat remote: No such file or directory

而且它会就此中断整个 batch,排在后面的命令一条都不执行。所以:

  • 远端没有这个文件 → 用普通 put
  • 远端有这个文件、且 0 < 远端字节 < 本地字节 → 加 -a 续传

怎么确认 -a 是真的在续传而不是重写?实测方法:远端先放一个 10 字节文件,
再 put -a 一个 2139 字节的文件,结果正好 2139 —— 说明只补了缺的 2129 字节。
若是 2149 就说明变成了「追加」,内容会是坏的。

注意续传前提是本地这个包和远端那份残缺是同一个文件。每次重跑都会重新打包,
源文件若在这期间变了,续传出来的东西会是坏的。这是续传机制的固有取舍。

4. 钥匙是「哪台认哪把」,不是「主用 / 备用」

不同机器的 authorized_keys 不一样,实测会出现「A 机器只认第一把、用第二把连必被拒」。
传输中断时千万别去换钥匙——日志最后只会留下一条误导性的 Permission denied,
看着像鉴权坏了,其实是网络断了。正确逻辑:

if ($txt -match 'Permission denied') { break }   # 钥匙不对,才换下一把
if ($try -lt 3) { Start-Sleep -Seconds 5 }       # 其它错误:同一把钥匙重试

5. 归档目录必须按「天」命名,续传才有用武之地

目录名写成 yyyy-MM-dd_HHmm 的话,断线重跑会落到另一个新目录,
上一趟传了一半的分卷就躺在旧目录里白干,跳过和续传永远触发不了。

改成 yyyy-MM-dd:同一天重跑必定回到同一目录,包名同样只到天
({别名}_{日期}_{卷标}.tar),于是:

  • 远端已有、字节数一致 → [已有] 跳过
  • 远端有残缺、比本地小 → [续传] 接着传

代价:一天只有一份异地备份。要一天多份的话,改用 staging 目录+传完改名。


带宽现实:先算时间,别指望「几分钟搞定」

实测多台机器之间传输,走组网层封装的地址与走同一个局域网,速度差别不大——
瓶颈常在物理链路本身,GB 级数据常见只有 2~3 MB/s:

7 GB 全量 ≈ 40 分钟     1 GB 分卷 ≈ 6 分钟

所以架构上必须三件事齐全:分卷 + 跳过已完成卷 + 断点续传。
两台在同一局域网时脚本会自动切到内网 IP,少一层封装,但别指望这带来质的提升。

打包反而很快:5 GB 用免压缩(tar -cf)只要 32 秒。
gzip 在几 GB 量级是纯亏——实测压缩 5 分钟才吐出 878 MB。


标准流程

  1. 单实例锁:留活着的进程 PID,超时 6 小时的锁当废纸处理(叠着跑两个会把带宽挤爆)
  2. 认自己:拿本机名去机器表里正则匹配
  3. 定位工具:ssh / MSYS 的 scp+sftp / 系统 tar
  4. 挑目标机:按 BackupTo 队列逐个试探(推 helper → probe → 剩余空间 < 3 GB 就跳过)
  5. 同网段直连检测:问对方拿局域网 IP,与本网段比对,命中再验一次 22 端口,不通就回退
  6. 推 helper 到目标机:scp 一个小脚本过去,负责 probe / mkdir / verify / rotate / usage
  7. 按天建目录:&lt;盘&gt;:\BackupHub\&lt;别名&gt;\&lt;日期&gt;
  8. 打包 + 分卷:默认 1 GB 一卷;单件就超过一卷的立即自成卷
  9. 传 + 回读:每卷传完都问目标机一次字节数
  10. 轮转 + 清理:按名字倒序保留最近 -Keep 份,删更早的整份;删本地临时包

传输段的正确写法(可直接抄)

# 传之前先问目标机:这份有多大?(-1 = 还没有)
$rsize0 = -1
foreach ($l in (Invoke-Remote -M $Target -Action &#x27;verify&#x27; -PathArg $remotePath)) {
    if ($l -match &#x27;^SIZE=(-?\d+)$&#x27;) { $rsize0 = [long]$Matches[1] }
}

# 远端已经有一份一模一样的,直接跳过
if ($rsize0 -eq $ar.Size -and $ar.Size -gt 0) { $okCount++; continue }

# 只有「远端有残缺」才加 -a
$append = &#x27;&#x27;
if ($rsize0 -gt 0 -and $rsize0 -lt $ar.Size) { $append = &#x27;-a &#x27; }

$rPut   = &#x27;/&#x27; + $remotePath            # /D:/BackupHub/...
$lPut   = To-Posix $ar.Local           # /c/Users/...
$batch  = Join-Path $env:TEMP (&quot;bk_put_&quot; + [guid]::NewGuid().ToString(&#x27;N&#x27;) + &#x27;.txt&#x27;)
Set-Content -LiteralPath $batch -Value @(&#x27;put &#x27; + $append + &#x27;&quot;&#x27; + $lPut + &#x27;&quot; &quot;&#x27; + $rPut + &#x27;&quot;&#x27;) -Encoding ASCII

$res = Run-Proc -Exe $sftpExe -ArgList ($baseArgs + @(&#x27;-i&#x27;, $key, &#x27;-b&#x27;, $batch, &quot;$user@$ip&quot;)) -WaitSec 10800
Remove-Item -LiteralPath $batch -Force -ErrorAction SilentlyContinue

# 传完回读一次,字节数对不上就算失败
$rsize = -1
foreach ($l in (Invoke-Remote -M $Target -Action &#x27;verify&#x27; -PathArg $remotePath)) {
    if ($l -match &#x27;^SIZE=(-?\d+)$&#x27;) { $rsize = [long]$Matches[1] }
}

远端命令输出怎么可靠地抓回来

这几台机器上,下面这些全部会挂或抛异常:&amp; ssh ... 2&gt;&amp;1、PowerShell 的 &gt; / 2&gt;、
.NET Process 接管管道、Start-Process(环境里同时存在 PATH 和 Path 两个键时会直接抛"字典中的关键字…")。

唯一稳的姿势:cmd /c &quot;exe ... &gt; 文件 2&gt; 文件&quot; + .NET Process + WaitForExit 超时杀进程。
完整实现见 scripts/Backup.ps1 里的 Run-Proc。

另外某些版本的 ssh 会往 stderr 狂吐 pipe(notify_pipe) failed 之类的噪音,
解析输出时一定要按规则行(如 SIZE=123)取,不要整段匹配。

目标机侧的活怎么干

scp 一个小 helper 脚本到目标机临时目录,再用 ssh ... -File 调它,
动作走符号化的 KEY=value 输出(ROOT= / FREEG= / MKOK / SIZE= / ROT=DEL:xxx)。
别让远端回中文,距离一长编码必坑。helper 必须是纯 ASCII,且存成 UTF-8 BOM。


PowerShell 5.1 的两个前置(忘了就白干)

  1. .ps1 要存成 UTF-8 BOM,否则 PS 5.1 按 GBK 读,中文字面量变乱码,
    报出来的错全是假的("string missing terminator" / "missing }")。
  2. 被工具误注入过 &lt;/...&gt; 之类标记的文件,要先用正则清掉,否则报 &lt; : 无法将…识别为 cmdlet。

端到端验证协议(别拿 7 GB 试)

  1. 先复制主脚本做一份小数据集测试副本,把本机那份 $Sets 换成一个几十 KB 的目录,
    只验证链路(打包 → 上传 → 回读 → 轮转 → 清理),几秒钟出结果。
  2. 然后才跑真实全量。
  3. 必看的三个日志标志:
    STAGE-7 mkdir D:/BackupHub/&lt;别名&gt;/&lt;日期&gt; ← 目录是「天」粒度 STAGE-8 pack ok &lt;卷标&gt; size=... secs=... ← 打包耗时(几十秒才正常) [OK] &lt;包名&gt; xxx MB (对方已回读确认) ← 回读校验过了才算数
  4. 速率核算:隔两分钟查一次远端同名文件的字节数,两次差值 ÷ 秒数。
    低于 2 MB/s 先想想是不是别的进程在挤带宽。

清理协议(喊停 / 要撤销时)

每一步看清了再动手,按顺序:

  1. 停后台任务 / 杀残留进程(sftp / tar)
  2. 本机临时打包目录 %TEMP%\BackupHub —— 实测能攒到 14 GB,占地的主犯
  3. 目标机 &lt;盘&gt;:\BackupHub\&lt;别名&gt;\&lt;日期&gt; —— 那半截包
  4. %LOCALAPPDATA%\BackupHub\running.lock —— 不删的话下次跑会被单实例锁直接拒绝
    (同目录的 keycache.txt / last.txt 是钥匙缓存和上次备份时间,可留)

删之前先列一遍给用户看,删完再列一次复核。

每台机器都要扫,别只扫源机和目标机

只要调过脚本,每台机器都可能留下:&lt;各盘&gt;:\BackupHub、%TEMP%\BackupHub、
%LOCALAPPDATA%\BackupHub、%TEMP%\bk_helper.ps1、桌面上的诊断件和日志。

在远端做扫描 / 删除,用 scp 上去的 PowerShell 脚本跑,别在 ssh 命令行里拼 cmd 命令——
Windows 路径里的反斜杠和 2&gt;nul 经 ssh 传过去会被吃掉(会拿到 参数格式不正确 - &quot;BackupHub&quot;)。

写这种远端脚本时有三个坑(都踩过):

  • $env:TEMP / $env:USERPROFILE 可能是空的。经 ssh 非交互拉起的会话不保证有这些变量,
    Join-Path $env:TEMP &#x27;x&#x27; 会得到空值然后报参数绑定错误。一律写死绝对路径。
  • 脚本里的中文字面量会变乱码(同上文 BOM 那条)。要么加 BOM,
    要么用字符码拼名字:[string][char]0x5907 + [string][char]0x4EFD + ...。
  • %TEMP%\bk_helper.ps1 有可能变成目录(某次 scp 把文件写成了目录,里面还套同名文件)。
    清理时对「文件」和「目录」两种形态都试一次。

删不掉的文件怎么办

先查属性:不是只读、却连改名都失败,就是远端有进程握着句柄。

⚠️ 别自己动手杀远端进程:先报给用户让他定。两个几百字节的文本文件,留着比冒风险强;
或者等下次到那台机器跟前 / 重启后再删。


排错速查

报错 真正的原因 怎么改
stat C:UsersADMINI~1...: No such file or directory batch 里本地路径没转 POSIX 用 To-Posix
No such file or directory(远端) 远端路径缺前导斜杠 D:/x → /D:/x
stat remote: No such file or directory 对不存在的文件用了 -a 首次上传用普通 put
Permission denied (publickey...) 钥匙拿错了(或传输中断后误换过钥匙) 按机器逐个试,认准后缓存
pipe: Unknown error 用了 Win32-OpenSSH 的 scp/sftp 换 MSYS2 版
参数格式不正确 - &quot;xxx&quot; ssh 远端命令行里的反斜杠被吃掉 改用上传的 ps1 脚本执行
Connection reset / 跑到一半断 带宽挤爆或对方撑不住 分卷调小、换目标机
tar 退出码非 0 个别文件被占用,已跳过 把 tar 的 stderr 前几行打出来看漏了谁

边界声明

不做:跨平台的 Linux / macOS 备份;块级快照与系统镜像;备份内容的加密压缩一体化;
无人值守的计划任务配置(请自行配「计划任务」调本脚本)。
也不替用户判断「哪些目录值得备份」——这件事必须由人拍板。

资源

  • scripts/Backup.ps1 —— 跑通版主脚本:单实例锁、候选目标机、LAN 直连检测、按天归档、
    分卷、续传、回读校验、轮转。顶部机器表需自行填写。
  • scripts/bk_helper.ps1 —— 目标机侧助手(probe / mkdir / verify / usage / rotate / ips),纯 ASCII + BOM
  • scripts/BackupRun.ps1 —— 启动器模板,支持传入目标机别名

典型调用:

powershell powershell -NoProfile -ExecutionPolicy Bypass -File .\BackupRun.ps1 -Target 你的异地机别名

本机 PowerShell 5.1 下,含中文的 .ps1 必须 UTF-8 带 BOM,否则字面量会乱码
(典型症状:某个中文文件名的判断永远为 False)。
另外,本机禁止用 &lt; &gt; 尖括号占位符直接写进 .bat——cmd 会把它们当重定向符。
所以启动器直接做成 .ps1,少一层坑。

常见问题

5 问
答案由本站依据条目字段整理
多台 Windows 之间的异地互备(SSH 分卷备份 + 断点续传)怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_878e6d7a/remote-win-backup-mesh。安装方式为未标注。装完刷新技能列表或重开客户端。

多台 Windows 之间的异地互备(SSH 分卷备份 + 断点续传)支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

多台 Windows 之间的异地互备(SSH 分卷备份 + 断点续传)权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

多台 Windows 之间的异地互备(SSH 分卷备份 + 断点续传)收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

多台 Windows 之间的异地互备(SSH 分卷备份 + 断点续传)用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 未标注。