游客发表
如果你在 Windows 上敲过 ssh user@host,十有八九用的就是 PowerShell。但很多人只把它当成一个“能连服务器的黑框”,连上去之后还是习惯性切到 bash,或者干脆开个 PuTTY。说实话,有点浪费。PowerShell 自带的 SSH 客户端(基于 OpenSSH)比大多数人想的要顺手,尤其是当你把它和 Windows 自己的管道、对象模型搅在一起的时候。
我第一次认真用 PowerShell 的 SSH 是在一台跳板机上。当时需要从 Windows 笔记本直接拉取远程 Linux 的日志,然后本地过滤。以前的做法是:ssh 连上去,cat、grep、awk 一条龙,最后复制粘贴回本地。那次我试着写了个单行命令:
ssh deploy@192.168.10.42 "tail -n 200 /var/log/nginx/access.log" | Select-String "POST /api" | ForEach-Object { $_.Line -replace '.*?"(.*?)".*', '$1' } 结果直接输出了一批干净的 API 路径。没有中间文件,没有手动复制。那一刻我才意识到,PowerShell 的 SSH 不是“另一个终端”,而是把远程命令当成了本地管道的一个数据源。这跟 Linux 下用 ssh host command 再管道给本地工具是一个道理,但 Windows 用户很少这么干。
默认情况下,Windows 10 1809 之后已经内置了 OpenSSH 客户端。你可以在 PowerShell 里直接 ssh -V 看看版本。如果没有,用管理员权限跑一行 Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 就完事。不需要装 Git Bash,也不需要 Cygwin。但这里有个细节:PowerShell 的 ssh 命令和 Linux 下的行为几乎一致,除了一个坑——路径里的反斜杠。比如 scp 传文件时,C:\Users\me\file.txt 要写成 C:/Users/me/file.txt 或者用引号包起来,否则远程 shell 会把反斜杠当转义符吃掉。我见过不少人卡在这一步,以为 SSH 坏了。
ssh-keygen 和 ssh-copy-id,但 Windows 上根本没有 ssh-copy-id。你得手动把公钥内容追加到远程的 ~/.ssh/authorized_keys。用 PowerShell 可以这么干:type $env:USERPROFILE\.ssh\id_rsa.pub | ssh user@host "cat >> ~/.ssh/authorized_keys"type 是 Get-Content 的别名,管道传的是字符串,不是文件流。远程的 cat 会逐行追加,不会覆盖。 另一个让我觉得舒服的地方是 SSH 配置文件的复用。Windows 下路径是 $env:USERPROFILE\.ssh\config,格式和 Linux 完全一样。你可以写 Host myserver、HostName 10.0.0.5、User admin、IdentityFile ~/.ssh/id_ed25519。然后 PowerShell 里直接 ssh myserver 就上去了。不用记 IP,不用每次输用户名。我甚至会在配置里加 LocalForward 8080 localhost:80,把远程的 Web 服务映射到本地,调试 API 的时候特别省事。
但 PowerShell 的 SSH 也不是没毛病。最烦的是交互式命令。比如你 ssh host 上去后运行 top 或者 vim,PowerShell 的终端有时会显示错位,尤其是窗口大小变化的时候。这不是 SSH 的问题,是 Windows 控制台宿主的历史遗留。解决办法是用 Windows Terminal 代替默认的 conhost,或者干脆在 SSH 命令后面加 -t 强制分配伪终端。我现在的习惯是:只要远程命令需要交互,一律 ssh -t user@host。虽然多打两个字符,但省心。
还有一点,PowerShell 7 之后跨平台好了很多,但 Windows PowerShell 5.1 依然默认使用 UTF-16 LE 编码。当你通过 SSH 把远程输出重定向到本地文件时,如果远程是 UTF-8,本地可能会变成乱码。我踩过一次坑:从远程 cat 一个中文日志,保存到本地用记事本打开全是问号。后来在命令前加 $OutputEncoding = [System.Text.Encoding]::UTF8 才解决。或者直接用 ssh host "command" | Out-File -Encoding utf8 file.txt。别小看编码,它能让你的自动化脚本在半夜三点莫名其妙地失败。
最后说个真实场景。我们团队有台 Windows 构建机,需要定期从 Linux 制品库拉取二进制包,然后跑签名工具。以前用 pscp 加批处理,又慢又容易断。后来改成 PowerShell 脚本:
$remoteFiles = ssh builder@artifacts "ls -1 /release/*.zip" foreach ($f in $remoteFiles) { scp "builder@artifacts:$f" C:\builds\ if ($LASTEXITCODE -ne 0) { Write-Error "拉取失败: $f" } } 配合 Windows 任务计划,每天凌晨自动跑。没有第三方工具,没有额外的 SSH 客户端。就用系统自带的 OpenSSH 和 PowerShell。稳定跑了半年多,只因为网络抖动重试过两次。所以,别再把 PowerShell 的 SSH 当成一个简单的远程登录工具了。它就是一个完整的、可编程的远程执行通道。你写 bash 脚本能做的事,在 PowerShell 里一样能做,而且还能直接用上 ConvertFrom-Json、Export-Csv 这些原生命令。花点时间熟悉一下,比装一堆 GUI 工具划算得多。
友情链接