1. 问题现象
这次问题不是单纯的 SSH 连不上,而是 Cursor 在多层远程链路中某一层失败:
text
Windows Cursor
-> Remote SSH 连接远端宿主机 192.168.206.112 / 192.168.206.140
-> Cursor Server 在远端宿主机启动
-> Dev Containers 尝试 attach 到 Docker 容器 magatron / f3673e625a77
-> 容器内 Cursor Server / extension host / WebSocket 连接失败
常见报错包括:
text
Failed to connect to the remote extension host server
Error: WebSocket close with status code 1006
text
Could not fetch remote environment
text
Socket-mode code server reported /tmp/cursor-remote-ssh-;
expected /tmp/cursor-remote-ssh-xxxx/code.sock
text
No remote exec server found for authority: dev-container...@ssh-remote...; using local
text
Failed to read .gitconfig:
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
text
EADDRINUSE: address already in use 127.0.0.1:37265
2. 关键判断
2.1 SSH 层通常是成功的
日志里多次出现:
text
SSH connection established
以及:
text
Server install command exit code: 0
这说明 SSH 本身不是主要问题。
2.2 远端宿主机 Cursor Server 也能启动
日志里出现过:
text
exitCode==0==
isFatalError==false==
codeListeningOn==/tmp/cursor-remote-ssh-.../code.sock==
说明远端宿主机上的 Cursor Server 能启动。
2.3 Docker 本身也基本正常
日志里出现:
text
docker info: Command completed with exit code 0
docker inspect f3673e625a77: Command completed with exit code 0
说明 Docker 服务正常,容器也能被 inspect 到。
2.4 真正失败点在 Cursor Remote-Containers / Dev Containers 上下文
最关键的报错是:
text
No remote exec server found for authority: dev-container...@ssh-remote...; using local
随后出现:
text
Failed to read .gitconfig:
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
这说明 Cursor 本来应该通过远端 SSH 上下文去 attach Docker 容器,但过程中 remote exec server 上下文丢失,导致 Cursor 退回到本地上下文,最终路径解析出错。
3. 主要原因汇总
原因 1:Cursor Remote-SSH 输出被 Windows 终端控制字符污染
日志中出现大量类似内容:
text
Microsoft Windows [版本 ...]
C:\Users\...\cmd.EXE
\x1b[10;40H
同时 socket 路径被截断:
text
Socket-mode code server reported /tmp/cursor-remote-ssh-;
expected /tmp/cursor-remote-ssh-xxxx/code.sock
说明 Cursor 在解析远端返回的 socket 路径时,被终端控制字符、换行或 cmd 输出污染。
解决方向:
- 关闭 socket mode
- 关闭登录终端显示
- 使用干净的 SSH config
- 避免
.bashrc输出欢迎信息、echo、clear、conda activate等内容
原因 2:Cursor / DevContainer 残留进程和 socket 文件冲突
日志中多次出现:
text
Multiplex server script is already running
Code server script is already running
Server script is already running
这说明旧的 Cursor Server、multiplex server、forwarder、devcontainer-cli 进程仍在运行。它们可能持有旧 token、旧 socket 或旧端口,导致新连接失败。
解决方向:
- 杀掉旧 Cursor 相关进程
- 删除远端
/tmp/cursor-remote-ssh-* - 删除远端
/tmp/devcontainer-cli-* - 删除容器内
/root/.cursor-server
原因 3:Dev Container 端口转发冲突
日志里出现:
text
EADDRINUSE: address already in use 127.0.0.1:37265
这说明某个本地或远端转发端口已经被占用。Cursor 会不断尝试新的 forwarder,但如果状态混乱,最终会导致 extension host 连接失败。
解决方向:
- 关闭本地 Cursor
- 杀掉本地 ssh.exe
- 清理远端 forwarder.js / devcontainer-cli
- 避免从旧的 Recent Project 直接恢复连接
原因 4:Cursor Dev Containers 缓存损坏或上下文丢失
关键报错:
text
No remote exec server found for authority: dev-container...@ssh-remote...; using local
以及:
text
The "path" argument must be of type string. Received undefined
这说明 Cursor 的 Remote Containers 状态损坏,或者从旧的 Recent Container 入口进入时没有正确拿到 SSH 上下文。
解决方向:
- 清理本地 Cursor 的
anysphere.remote-containers缓存 - 不要直接点旧的 Recent Project
- 先 Remote SSH 到宿主机,再 Attach Running Container
原因 5:.gitconfig / GPG / known_hosts 缺失引发干扰
日志里有:
text
Failed to read /home/pcljgy/.ssh/known_hosts
text
gpg: Fatal: can't open '/home/pcljgy/.gnupg/trustdb.gpg'
这些一般不是根因,但会增加连接过程中的异常分支。后面真正致命的是 .gitconfig path 为 undefined。
解决方向:
- 在远端宿主机创建空的 known_hosts
- 初始化
.gnupg - 关闭 Dev Containers 自动复制 Git 配置
原因 6:在 Docker 内执行 pkill -u "$USER" 时 $USER 为空
Docker 内报过 pkill 使用帮助,原因通常是执行了:
bash
pkill -u "$USER" -f cursor-server
但容器内 $USER 为空,实际变成:
bash
pkill -u -f cursor-server
所以 pkill 报 usage。
解决方式:
容器内不要用 -u "$USER",改用:
bash
pkill -f cursor-server || true
宿主机上可以用:
bash
pkill -u "$(id -u)" -f cursor-server || true
4. 推荐的一次性修复流程
4.1 Windows 本地关闭 Cursor 和 SSH
在 Windows PowerShell 执行:
powershell
taskkill /F /IM Cursor.exe
taskkill /F /IM ssh.exe
如果 ssh.exe 中有其他重要连接,不要直接杀所有 ssh.exe,可以用更精确的方式:
powershell
Get-CimInstance Win32_Process |
Where-Object { $_.Name -eq "ssh.exe" -and $_.CommandLine -like "*cursor-remote-ssh*" } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
4.2 清理本地 Cursor Remote Containers 缓存
PowerShell 执行:
powershell
Rename-Item "$env:APPDATA\Cursor\User\globalStorage\anysphere.remote-containers" `
"$env:APPDATA\Cursor\User\globalStorage\anysphere.remote-containers.bak" `
-ErrorAction SilentlyContinue
如果仍失败,再清理 Remote SSH 缓存:
powershell
Rename-Item "$env:APPDATA\Cursor\User\globalStorage\anysphere.remote-ssh" `
"$env:APPDATA\Cursor\User\globalStorage\anysphere.remote-ssh.bak" `
-ErrorAction SilentlyContinue
4.3 配置 Windows SSH config
打开:
powershell
notepad $env:USERPROFILE\.ssh\config
加入:
sshconfig
Host pcl112
HostName 192.168.206.112
User pcljgy
RequestTTY no
ServerAliveInterval 30
ServerAliveCountMax 3
TCPKeepAlive yes
LogLevel ERROR
测试:
powershell
ssh -T pcl112 "echo ok"
理想输出只应该是:
text
ok
如果出现欢迎语、乱码、conda 信息、颜色控制符,就说明远端 shell 启动脚本仍然污染输出。
4.4 远端宿主机补齐基础文件
登录远端宿主机:
powershell
ssh pcljgy@192.168.206.112
在宿主机执行:
bash
mkdir -p ~/.ssh ~/.gnupg
touch ~/.ssh/known_hosts
chmod 700 ~/.ssh ~/.gnupg
chmod 600 ~/.ssh/known_hosts
gpg --list-keys >/dev/null 2>&1 || true
4.5 清理远端宿主机 Cursor 残留
在 206.112 宿主机执行:
bash
pkill -u "$(id -u)" -f cursor-server || true
pkill -u "$(id -u)" -f multiplex-server || true
pkill -u "$(id -u)" -f cursor-remote || true
pkill -u "$(id -u)" -f devcontainer-cli || true
pkill -u "$(id -u)" -f forwarder.js || true
rm -rf ~/.cursor-server
rm -rf /tmp/cursor-remote-ssh-*
rm -rf /tmp/devcontainer-cli-*
rm -rf /run/user/$(id -u)/cursor-remote-* 2>/dev/null || true
4.6 清理 Docker 容器内 Cursor 残留
如果容器 ID 是 f3673e625a77,在宿主机执行:
bash
docker exec -u root f3673e625a77 sh -lc '
pkill -f cursor-server || true
pkill -f multiplex-server || true
pkill -f cursor-remote || true
pkill -f devcontainer-cli || true
pkill -f forwarder.js || true
rm -rf /root/.cursor-server
rm -rf /tmp/cursor-remote-ssh-*
rm -rf /tmp/devcontainer-cli-*
rm -rf /run/user/*/cursor-remote-* 2>/dev/null || true
'
如果容器里没有重要运行任务,可以重启容器:
bash
docker restart f3673e625a77
4.7 修改 Cursor 设置
打开:
powershell
notepad "$env:APPDATA\Cursor\User\settings.json"
加入或合并以下配置:
json
{
"remote.SSH.showLoginTerminal": false,
"remote.SSH.useLocalServer": false,
"remote.SSH.remoteServerListenOnSocket": false,
"dev.containers.copyGitConfig": false,
"remote.containers.copyGitConfig": false
}
重点配置说明:
json
"remote.SSH.remoteServerListenOnSocket": false
用于避免 socket mode 下 socket 路径解析和任意 TCP 转发问题。
json
"dev.containers.copyGitConfig": false,
"remote.containers.copyGitConfig": false
用于绕开 .gitconfig path undefined 相关问题。
4.8 正确重新连接流程
不要直接点 Cursor 首页的旧 Recent Project,例如:
text
Container magatron (f3673e625a77)
应该按这个顺序:
text
1. 打开 Cursor
2. Remote-SSH: Connect to Host...
3. 选择 pcl112 或 192.168.206.112
4. 等左下角显示已经 SSH 连接到远端宿主机
5. 再执行 Dev Containers: Attach to Running Container...
6. 选择 magatron / f3673e625a77
7. 再打开 /workspace 或 /root/workspace
5. 排查命令
5.1 判断 Docker 容器本身是否可进入
在远端宿主机执行:
bash
docker ps -a | grep f3673e625a77
docker inspect -f '{{.State.Status}} {{.State.Running}} {{.State.ExitCode}} {{.Name}}' f3673e625a77
docker exec -it f3673e625a77 bash
如果 bash 不存在:
bash
docker exec -it f3673e625a77 sh
如果手动 docker exec 都进不去,问题在 Docker / 容器本身,不是 Cursor。
如果手动 docker exec 能进去,但 Cursor 进不去,问题在 Cursor Remote Containers / 端口转发 / 缓存状态。
5.2 查看容器内 Cursor Server 日志
bash
docker exec -u root f3673e625a77 sh -lc '
ls -lh /root/.cursor-server/
tail -200 /root/.cursor-server/*.log 2>/dev/null || true
'
5.3 检查远端宿主机资源
bash
df -h
df -ih
free -h
ls -ld /tmp /run/user/$(id -u) ~
如果磁盘满了、inode 满了、/tmp 不可写,Cursor Server 也可能启动失败。
5.4 检查是否被 OOM 杀掉
bash
dmesg -T | tail -100 | grep -iE "killed|oom|cursor|node"
6. 最短可执行修复版
Windows PowerShell
powershell
taskkill /F /IM Cursor.exe
taskkill /F /IM ssh.exe
Rename-Item "$env:APPDATA\Cursor\User\globalStorage\anysphere.remote-containers" `
"$env:APPDATA\Cursor\User\globalStorage\anysphere.remote-containers.bak" `
-ErrorAction SilentlyContinue
远端宿主机
bash
mkdir -p ~/.ssh ~/.gnupg
touch ~/.ssh/known_hosts
chmod 700 ~/.ssh ~/.gnupg
chmod 600 ~/.ssh/known_hosts
pkill -u "$(id -u)" -f cursor-server || true
pkill -u "$(id -u)" -f multiplex-server || true
pkill -u "$(id -u)" -f cursor-remote || true
pkill -u "$(id -u)" -f devcontainer-cli || true
pkill -u "$(id -u)" -f forwarder.js || true
rm -rf ~/.cursor-server
rm -rf /tmp/cursor-remote-ssh-*
rm -rf /tmp/devcontainer-cli-*
rm -rf /run/user/$(id -u)/cursor-remote-* 2>/dev/null || true
容器内清理
bash
docker exec -u root f3673e625a77 sh -lc '
pkill -f cursor-server || true
pkill -f multiplex-server || true
pkill -f cursor-remote || true
pkill -f devcontainer-cli || true
pkill -f forwarder.js || true
rm -rf /root/.cursor-server
rm -rf /tmp/cursor-remote-ssh-*
rm -rf /tmp/devcontainer-cli-*
'
Cursor settings.json
json
{
"remote.SSH.showLoginTerminal": false,
"remote.SSH.useLocalServer": false,
"remote.SSH.remoteServerListenOnSocket": false,
"dev.containers.copyGitConfig": false,
"remote.containers.copyGitConfig": false
}
7. 最终结论
这次 Cursor 连接失败的核心不是 Docker 不可用,也不是 SSH 密码或网络问题。
更准确的结论是:
text
Cursor Remote-SSH 能连上宿主机,
Docker 容器也能被 inspect,
容器内 Cursor Server 也能安装并监听端口;
但 Cursor Remote-Containers 的远程上下文丢失或缓存状态损坏,
导致 attach 容器时退回本地上下文,最终 .gitconfig 路径变成 undefined,
并伴随 socket mode、端口转发和旧进程残留问题。
推荐的解决策略是:
text
清理本地 Cursor remote-containers 缓存
清理远端宿主机和容器内 Cursor 残留
关闭 socket mode 和 Git config 自动复制
不要从旧 Recent Project 直接恢复连接
先 Remote-SSH 到宿主机,再 Attach Running Container