ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

VS Code Remote-SSH 因 RemoteForward 端口冲突导致连接失败的排查与解决

VS Code Remote-SSH 因 RemoteForward 端口冲突导致连接失败的排查与解决 最近在 Windows 上使用 VS Code Remote-SSH 连接 Linux 服务器时遇到了一个比较隐蔽的问题普通 SSH 登录基本正常但 VS Code Remote-SSH 会直接失败日志中出现Error: remote port forwarding failed for listen port 10802 过程试图写入的管道不存在。 Failed to parse remote port from server output一开始容易把注意力放在 VS Code Server、SSH 客户端、Windows 管道或者远程安装脚本上但真正的根因其实是SSH 配置中的RemoteForward端口已经被另一个 SSH 会话占用而ExitOnForwardFailure yes又会让整个 SSH 连接因此直接退出。本文记录完整的排查过程以及后续遇到的 VS Code Remote-SSH / Dev Containers 配置兼容问题。1 问题现象本地环境大致如下WindowsVS CodeRemote-SSHGit for Windows 自带 OpenSSH远端 Linux 服务器SSH 配置中使用RemoteForward远端通过socat将代理端口转给 Docker 容器SSH 配置类似Host my-server HostName SERVER_IP Port SSH_PORT User USERNAME IdentityFile C:\Users\USER\.ssh\id_rsa RemoteForward 10802 ExitOnForwardFailure yes ServerAliveInterval 30 ServerAliveCountMax 3VS Code Remote-SSH 日志中真正关键的错误是Error: remote port forwarding failed for listen port 10802后面的过程试图写入的管道不存在。 Failed to parse remote port from server output实际上只是 SSH 进程提前退出后的连锁报错。2 先确认 SSH 客户端是否正常Remote-SSH 会尝试在本机 PATH 中寻找ssh.exe日志里可能会看到大量Checking ssh with C:\...\ssh.exe -V Got error from ssh: ... ENOENT这些通常不是问题。只要最终能找到某个可用 SSH例如C:\Program Files\Git\usr\bin\ssh.exe并成功输出版本OpenSSH_x.x就说明本机 SSH 客户端本身是正常的。所以排查重点应该放到remote port forwarding failed而不是前面那些ENOENT。3 检查远端端口是否已经被占用在远端服务器执行sudoss-lntp|grep10802如果看到类似LISTEN 0 128 127.0.0.1:10802 0.0.0.0:* users:((sshd,pid123456,fd9)) LISTEN 0 128 [::1]:10802 [::]:* users:((sshd,pid123456,fd7))说明10802已经被某个sshd子进程监听。也就是说已经存在一个 SSH RemoteForward 会话。查看具体进程ps-fp123456或者ps-aux|grep123456注意下面这种写法是不对的ps-aux|greppid123456因为ps输出中并不会出现字面量pid123456。还可以进一步检查该 SSH 会话对应的网络连接sudoss-tnp|grep1234564 为什么 RemoteForward 失败会导致整个 VS Code 连接退出关键在于 SSH 配置中的ExitOnForwardFailure yes它的含义是只要端口转发建立失败SSH 主连接也立即失败。因此实际流程是VS Code ↓ 启动 SSH ↓ 登录远端服务器 ↓ 申请 RemoteForward 10802 ↓ 10802 已经被占用 ↓ RemoteForward 创建失败 ↓ ExitOnForwardFailure yes ↓ SSH 直接退出 ↓ VS Code 远端安装脚本被中断 ↓ 出现“管道不存在” ↓ Failed to parse remote port所以真正的根因依旧只是RemoteForward 端口冲突5 为什么换一个 RemoteForward 端口后仍然可能失败一开始我尝试把10802换成10812但问题依旧存在。这时问题就不一定是“旧 SSH 会话占了旧端口”而可能是VS Code Remote-SSH 自己启动了多个 SSH 连接而每个连接都会重复执行同一个RemoteForward。例如VS Code SSH connection #1 ↓ 成功监听 10812 VS Code SSH connection #2 ↓ 再次请求监听 10812 ↓ 端口已被 connection #1 占用 ↓ 失败这种情况下不管把端口改成多少第二个 SSH 会话都会撞到第一个。验证方法很简单。VS Code 连接失败以后在服务器上立即执行sudoss-lntp|grep10812如果新端口此时已经被sshd占用就说明至少有一个 SSH 会话已经成功建立了 RemoteForward。6 一个很关键的现象关闭另一个 VS Code 窗口后就正常了后来发现只要把已经连接服务器的 VS Code 窗口关闭新连接就能正常建立。这说明问题和 VS Code Remote-SSH 的 SSH 会话复用方式高度相关。也就是说很可能存在这种情况VS Code 窗口 A ↓ SSH connection A ↓ RemoteForward 10802 成功 VS Code 窗口 B ↓ SSH connection B ↓ 再次 RemoteForward 10802 ↓ 失败而另一台电脑却没有这个问题说明两台电脑的 Remote-SSH 配置或者连接模式可能不同。7 尝试使用 useLocalServer可以在 VS Code 的settings.json中尝试{remote.SSH.useLocalServer:true}其目的之一是让多个 VS Code 远程窗口更倾向于复用本地 Remote-SSH 连接而不是每个窗口都完全独立启动新的 SSH 会话。对于包含固定RemoteForward的 SSH 配置这样可以降低重复绑定同一远端端口的概率。修改以后建议完全退出所有 VS Code 窗口在任务管理器中确认没有残留的Code.exe重新打开 VS Code再尝试连接。8 不要轻易关闭 useExecServer排查 Remote-SSH 时有一种常见建议是{remote.SSH.useExecServer:false}这个选项在某些 Remote-SSH 故障中可能确实有帮助。但是如果你的使用场景是本地 VS Code ↓ Remote-SSH 到 Linux 宿主机 ↓ Dev Containers ↓ Attach to Running Container那么关闭useExecServer可能产生新的问题。我实际遇到的表现是运行命令 remote-containers.attachToRunningContainerFromViewlet 错误: 出现未知错误也就是说Remote-SSH 本身能用了但无法继续 Attach 到远端 Docker 容器。因此对于 Remote-SSH Dev Containers 的组合更合适的配置是{remote.SSH.useLocalServer:true,remote.SSH.useExecServer:true}或者更简单{remote.SSH.useLocalServer:true}而让useExecServer保持默认值。9 比较推荐的配置最终更合理的思路是{remote.SSH.useLocalServer:true}而 SSH 配置保持Host my-server HostName SERVER_IP Port SSH_PORT User USERNAME IdentityFile C:\Users\USER\.ssh\id_rsa RemoteForward 10802 ExitOnForwardFailure yes ServerAliveInterval 30 ServerAliveCountMax 3这样既可以尽量避免多个 VS Code 窗口反复创建 SSH RemoteForward又不会破坏 Dev Containers over SSH 的使用。10 更稳定的方案将代理隧道和 VS Code SSH 解耦如果不希望 RemoteForward 受 VS Code Remote-SSH 生命周期影响更稳妥的方法是不要把RemoteForward写在 VS Code 使用的 Host 配置中。例如把RemoteForward 10802 ExitOnForwardFailure yes删掉只保留普通 SSH 配置Host my-server HostName SERVER_IP Port SSH_PORT User USERNAME IdentityFile C:\Users\USER\.ssh\id_rsa ServerAliveInterval 30 ServerAliveCountMax 3然后单独开一个 SSH 隧道C:\Program Files\Git\usr\bin\ssh.exe-N -R 10802 -o ExitOnForwardFailureyes -o ServerAliveInterval30 -o ServerAliveCountMax3 my-server其中-N表示只建立 SSH 隧道不打开远端 shell。这时整体结构变成Windows │ ├── 独立 SSH tunnel │ ssh -N -R 10802 my-server │ └── VS Code Remote-SSH ssh my-server服务器侧127.0.0.1:10802 ↓ SSH tunnel ↓ Windows 本地代理Docker 侧如果需要经过socatsocat TCP-LISTEN:10801,bindDOCKER_BRIDGE_IP,reuseaddr,fork\TCP:127.0.0.1:10802整体链路Docker Container ↓ DOCKER_BRIDGE_IP:10801 ↓ socat ↓ 127.0.0.1:10802 ↓ SSH RemoteForward ↓ Windows ↓ 本地代理这个方案最大的优点是VS Code Remote-SSH 开几个窗口都不会影响代理隧道。对于需要长期使用代理的远程开发环境我个人更推荐这种解耦方案。11 排查时最有用的几个命令检查 RemoteForward 端口sudoss-lntp|grepPORT查看对应进程ps-fpPID检查 SSH 网络连接sudoss-tnp|grepPID手动测试 SSHC:\Program Files\Git\usr\bin\ssh.exe-vvv my-server重点关注remote forward remote port forwarding failed Address already in use等信息。12 总结这类问题最容易误导人的地方是 VS Code 最终显示的报错往往是Failed to parse remote port或者过程试图写入的管道不存在但它们经常并不是根因。如果日志前面出现remote port forwarding failed for listen port ...优先检查远端端口是否已经被其他sshd占用是否存在旧 SSH 会话VS Code 是否同时启动了多个 SSH 连接ExitOnForwardFailure yes是否导致整个 SSH 连接退出remote.SSH.useLocalServer是否可以改善多窗口连接复用如果还需要 Dev Containers不要随意关闭remote.SSH.useExecServer最稳定的做法是将代理 SSH 隧道和 VS Code Remote-SSH 分离。最终可以把整个问题归纳为一句话RemoteForward 本身没有问题真正的问题是固定远端监听端口与 VS Code 多 SSH 会话之间发生了生命周期冲突。
返回列表