一、远程部署的痛点:云上 Windows 没有"拖文件"
我们的站点跑在腾讯云轻量 Windows 上,没有 Docker、没有好用的scp。最顺手的原生通道是 winrs(Windows Remote Shell)——一条命令就能在远端执行 PowerShell。但"能执行"和"能把本地文件可靠送上去"是两码事,中间的坑能让你怀疑人生。
二、直接传文件?别想了
winrs 走的是命令行,没法直接传二进制。早期我们试过把文件内容塞进命令参数,结果遇到三连击:
坑 1 · 特殊字符炸命令: 文件里的
& | < > 被远端 shell 当成语法,整条命令作废。坑 2 · 超长参数被截断: 大文件一次性塞进命令行,超出长度直接丢尾。
坑 3 · 中文/编码乱码: 非 ASCII 内容传过去变问号,HTML 直接废。
三、可靠模式:Base64 分块 + certutil 解码
最后稳定下来的做法,核心是"把文件变成纯 ASCII 文本,再分小块喂过去":
1. 本地转 Base64
把文件读成字节 → Base64 字符串。Base64 只有 A-Z a-z 0-9 + / =,全是 ASCII,绝不会触发 shell 特殊字符。
2. 切成 4000 字符的小块
每块用 Add-Content -Encoding ascii 追加到远端一个 .b64 临时文件。小块能保证单条 winrs 命令不超长、不被截断。
3. 远端 certutil 解码落地
全部块追加完后,一条 certutil -decode 临时.b64 目标文件 还原成原始二进制。这一步是 Windows 自带、零依赖、最稳的。
4. SHA256 校验兜底
本地和远端各算一次 SHA256,不一致就重传,一致才删临时文件。这一步救过我们好几次"看似传完其实少了尾巴"的事故。
一句话流程: 本地 Base64 → 分块 ASCII 追加 → 远端 certutil 解码 → SHA256 比对。
四、cmd 里的语法雷区
远端执行的是 Windows 命令,很多"理所当然"的写法会被拦或失效:
if exist/timeout/rmdir在受限 shell 下行为不一致,能不用就不用,改用 PowerShell 的Test-Path/Remove-Item;- 路径里的空格要引号包裹,但引号在 winrs 传参时又要多层转义——尽量用无空格路径(如
C:\www)省去麻烦; - 别在一条命令里塞
&&长链,任何一段失败整条崩,拆成多条分步执行更好排查。
五、失败自愈:重试 + 清理
winrs 偶尔网络抖动会断。我们的部署脚本做法是:
- 单条命令失败自动重试(最多 4 次,间隔 2 秒);
- 临时
.b64文件每次先删再写,避免上次残留污染; - 校验失败直接抛错并保留临时文件,方便人工看哪块坏了;成功才清理。
给后来者: 别追求"一条命令搞定"。分块、解码、校验、清理,四步各司其职,哪步出问题一目了然,比炫技式一行流好维护十倍。
六、适合谁、注意什么
这套适合云上 Windows、无 Docker、要免费传文件的场景。注意三点:① 传输过程明文走网络,别传密钥/证书私钥这类极度敏感物;② 大文件(几百 MB 以上)分块会很慢,那是该上对象存储的信号;③ 每次部署完用 curl 探一下上线页是不是 200,非 200 立刻告警。
一句话: winrs + Base64 分块 + certutil 解码,是云上 Windows 免费、零依赖、最可靠的部署通道——前提是别跳过 SHA256 校验。