zcode ssh连接服务器

zcode ssh连接服务器


用了Zcode几个月,都是本地项目开发,也没有远程主机,没试过zcode SSH。早上摸鱼想尝试一下zcode SSH连接远程主机开发试下。踩坑之路由此开始,记录如下。

一台阿里云 ECS(2 核 / 1.6GB 内存 / 3Mbps 固定带宽 / 40GB 磁盘),上面跑着 1Panel、OpenResty、DSH 和个人博客。想在 ZCode 里通过 SSH 把它配置成远程工作区,在服务器上直接开发。

一、安全组22端口放行问题

配置连接提示 SSH 直接连不上,ETIMEDOUT,安全组明明已经加了当前 IP /32 白名单,还是不通。

机器活着、80/443 都放行,唯独 22 被拦 —— 问题锁定在安全组的 22 端口那条规则上。

网络IP 是漂的,/32 管不住

多源交叉验证时发现了真正的问题——同一个下午,不同时间查到的出口 IP 不一样:

1
2
curl -s --noproxy '*' https://api.ip.sb/ip      # 888.888.88.100
curl -s --noproxy '*' http://httpbin.org/ip # 888.888.88.101

在 888.888.88.x 池里轮换。白名单写死 .100/32,IP 漂到 .101 时就被静默丢弃——这解释了”明明加了白名单还是超时”。

解决

安全组 22 端口授权对象从 /32 放宽到整个 C 段:

1
888.888.88.0/24    TCP 22    入方向    允许

/32 = 锁死一个门牌号;/24 = 放行整个小区(最后一段随便变)。家宽/手机热点这类会漂的 IP,用 /24 兜底;有固定公网 IP 的场景才用 /32。

改完验证:nc -vz -w 5 IP 22 显示 succeeded,ZCode 顺利连上。

二、连上没多久,整台服务器”卡死”

连上远程工作区、开始干活后不久,网站进不去了,SSH 也连不上了。阿里云监控的带宽曲线显示:公网带宽瞬时打满,时间点正是 ZCode 连接的时刻。

根因:ZCode 重连时自动下载资产,不限速

ZCode 通过 SSH 连接远程工作区时的固定流程:

1
检测远端环境 → 校验资产(CLI 运行时等) → 不完整就自动重新下载安装

关键在于:

  1. 这个下载不需要用户任何操作,重连就触发;
  2. 连接配置里 assetInstallMode: remote-download,资源直接从 ZCode CDN 下到服务器;
  3. 下载没有限速,3Mbps(≈375KB/s)的小水管瞬间 100% 占满。

带宽被打满的典型症状(这次全部命中):

  • TCP 三次握手能成功(nc 测试端口是通的)
  • 但 SSH 卡死在 Connection timed out during banner exchange——banner 都吐不出来
  • HTTP 请求 15 秒无响应或 5 秒+才返回
  • ping 反而正常(ICMP 优先级高)

止损与防护:给 curl/wget 套全局限速 wrapper

ZCode 的远端下载用的是系统 curl/wget(且 ZCode 本身没有下载限速配置项)。在服务器上用 PATH 优先级做一层 wrapper——/usr/local/bin 排在 /usr/bin 前面,不动系统文件,随时可删:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mkdir -p /usr/local/bin

cat > /usr/local/bin/curl <<'EOF'
#!/bin/bash
echo "$(date +%F\ %T) curl $*" >> /tmp/curl-wrapper.log
exec /usr/bin/curl --limit-rate 300K "$@"
EOF
chmod +x /usr/local/bin/curl

cat > /usr/local/bin/wget <<'EOF'
#!/bin/bash
exec /usr/bin/wget --limit-rate=300k "$@"
EOF
chmod +x /usr/local/bin/wget

效果:所有下载自动限到 300KB/s ≈ 2.4Mbps,给 SSH 和网站永久留出 0.6Mbps 余量。日志落在 /tmp/curl-wrapper.log,能看到每次下载的时间与参数。

想解除限速时:rm /usr/local/bin/curl /usr/local/bin/wget。

顺手学到的一课:mirrors.aliyun.com 对阿里云 ECS 解析到内网,走内网带宽,不受 3Mbps 公网限制。在服务器上装软件尽量用阿里云镜像源,完全不占公网。

排查路上的两个暗坑

这轮排查中 SSH 一直”连不上”,其实混入了两个和带宽无关的问题,被 2>/dev/null 吞掉错误后全都伪装成了”带宽没恢复”:

坑 A:私钥权限太开放

1
2
3
WARNING: UNPROTECTED PRIVATE KEY FILE!
Permissions 0644 for 'root.pem' are too open.
This private key will be ignored.

chmod 600 root.pem 解决。

坑 B:服务器重启后 host key 变了

1
Host key verification failed.

ssh-keygen -R <ip> 清掉旧指纹,用 StrictHostKeyChecking=accept-new 重新接受。

教训:排查脚本里别无脑 2>/dev/null,超时和认证失败表现一样(都是连不上),但处理方式完全不同。

三、1Panel 管理页面请求超时——真凶居然是内存

限速部署完、资产装完后消停了一阵,然后 1Panel 管理页面开始请求超时。公网 SSH 又挤不进去,只能走阿里云控制台 VNC(走内部链路,不占公网带宽,服务器再堵也能进——这是小水管机器最后的救命通道)。

VNC 里一顿诊断,结果反转:

1
速率: 收 0.01 MB/s, 发 0.00 MB/s        ← 带宽几乎是空的,根本没在下载!

但 ps 输出里藏着真凶:

1
2
root  44  11.5  0.0      0     0 ?  S  10:47  26:07 [kswapd0]      ← 内存回收进程,4小时跑了26分钟CPU
root 8621 0.7 18.2 12067740 312284 ? Ssl 14:02 0:14 zcode-cli ← 占了18%内存(312MB)

free -h 定案:

1
2
3
               total   used   free   shared  buff/cache  available
Mem: 1.6Gi 1.6Gi 81Mi 4.5Mi 99Mi 57Mi
Swap: 0B 0B 0B ← 完全没有 swap!

1.6GB 内存耗尽(available 只剩 57Mi),且没有配置任何 swap。 系统在无 swap、内存耗尽的状态下疯狂回收页缓存(buff/cache 被榨到只剩 99Mi),所有进程排队等内存,CPU 被 kswapd0 吃掉——SSH 握不出手、1Panel 全超时、网站 5 秒+响应。之前以为是”带宽拥塞”的症状,其实是服务器喘不上气。

内存账单:1Panel(100MB)+ Docker 两个容器 + deepseek-harness 的 node 服务(240MB)+ zcode-cli(312MB)+ 阿里云盾双进程 → 1.6GB 塞满。

解决

止血:杀掉 zcode-cli,立刻回收 312MB,服务秒恢复。

治本:加 2GB swap 当缓冲垫:

1
2
3
4
5
6
7
8
9
10
11
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

# 重启持久化
echo '/swapfile none swap sw 0 0' >> /etc/fstab

# 内存真不够时才动用 swap,平时不拖慢速度
echo 'vm.swappiness=10' >> /etc/sysctl.conf
sysctl -p

验证:

1
2
Swap:  2.0Gi   0B   2.0Gi   ← 生效
Mem available: 57Mi → 619Mi ← 杀进程后

有了 swap,以后内存再紧张也只是轻微变慢,不会再陷入”SSH 挤不进、面板全超时”的死锁。

复盘:三类问题

现象 直觉以为 实际原因 关键判据
SSH ETIMEDOUT 网络/服务商问题 白名单填了代理 IP + 家宽 IP 漂移 ping 通、80/443 通、唯独 22 不通
服务器整体卡死 被攻击 ZCode 自动下载资产打满 3Mbps TCP 通但 banner 超时;带宽曲线与下载时间吻合
1Panel 超时 又是带宽 内存耗尽 + 无 swap kswapd0 高 CPU;收发速率≈0;available 57Mi

小水管小内存服务器生存指南

最后沉淀几条通用经验:

  1. 白名单 IP 要用直连方式查(curl --noproxy '*'),挂代理时浏览器看到的 IP 是节点的;动态 IP 用 /24 兜底。
  2. 诊断分层走:nc 测 TCP → ping 测 ICMP → curl 测应用层。”TCP 通但应用层超时”= 带宽拥塞或服务器过载,”ping 都不通”= 路由/宕机。
  3. VNC 是最后的通道:公网再堵,阿里云 VNC 走内部链路永远能进。平时把 VNC 密码放好,关键时刻救命。
  4. 3Mbps 固定带宽几乎经不起任何下载任务:要么给 curl/wget 做限速 wrapper,要么改按流量计费(峰值 100Mbps,偶尔下载总费用几毛钱)。
  5. 小内存机器必配 swap:1.6GB 内存无 swap = 一旦 OOM 边缘就是全身瘫痪。2GB swapfile + swappiness=10,十分钟的事。
  6. 远程开发工具很重:zcode-cli 服务端进程一跑就是 300MB+,小内存机器接不住这种”桌面级体验”。要么升配到 4GB,要么接受它一来网站就慢。
  7. 排查脚本别吞 stderr:2>/dev/null 会把”认证失败”伪装成”网络不通”,方向就排查歪了。

环境:macOS + Clash / 阿里云 ECS 2C1.6G 3Mbps / ZCode 远程工作区(SSH remote-download 模式)/ 1Panel v1