只读调查 · 10 月下旬的一次快照

登录节点过载调查

登录节点没有宕机,是被拖慢了。大部分进程卡在等 IO,swap 已经用满。会话记录因为一个节点级故障不回收,又碰上一个客户端反复重连,积累了几千条。我们自己的占用很小,codex 也没有在泄漏。

1 分钟 load503几十个核的机器,15 分钟均值还在往上走。严重
ssh 登录耗时157s另一次连 SSH banner 都没等到就超时了。严重
卡在 IO 的进程66真正在跑的只有 19 个,swap 已经用满。严重
会话记录约 2,700九成以上是不回收的空壳。注意

登录为什么卡

Linux 的 load 把等 IO 的进程(D 状态)也算在内。load 503 而在跑的只有 19 个,说明机器不是算不过来,是卡在 NFS 读写和换页上。sshd 能回 banner,但登录还要走 PAM、建会话、读家目录,每一步都在排队。

四次登录尝试

从计算节点 ssh 到登录节点,条长 = 用了多少秒

进去了没进去

CPU 时间花在哪

vmstat 每秒采样,两次实时读数,单位 %

等 IO(wa)内核(sy)用户程序(us)空闲(id)

会话表为什么涨

每次 ssh 登录,logind 都会记一条会话。这台机器有个节点级故障,有些会话结束后记录不回收,变成空壳,已经积累了几千条。最多的一个账号约有 2,500 条,过去一小时还在新增,看起来是某个客户端在反复重连,每次都起 bash 和 conda,conda 又卡在 NFS 上。这种"客户端反复重连、每次留下进程"的模式以前也出现过。

会话记录

最多的一个账号和其余所有账号

过去一小时新开的会话

按会话记录里的创建时间,只统计了前几名

卡在 IO 的进程,按程序

D 状态进程,各次采样之间会浮动

我们自己在登录节点上的东西

几十个进程、不到 1 GiB 内存、大约 0.1 个核,不是这次的原因。快照里我们一度排 CPU 第一,那是测量用的 ps 自己:ps 的 %CPU 是累计 CPU 时间除以存活时间,刚启动的 ps 会显示几百 %。不过有两样东西按我们自己定的规矩不该在这台机器上。

东西内存结论
一个查看用的 tmux,每个窗口连一条 ssh 到会话所在的节点约 11 MB正常,留着
一个 Claude Code 会话的副本,和它的 MCP 服务约 420 MB不该在这里,此刻也卡在 IO 上。建议退掉,计算节点上那份照常工作
Cursor 远程服务端,和两个成了孤儿的启动循环约 134 MBCursor 连到了登录节点。改连计算节点后清掉
一个 Claude 远程服务约 6 MB很小,可留
自己开着的几个终端约 11 MB正常

codex 有没有在泄漏

没有。在任意计算节点上逐个试 codex 临时目录里的文件锁,加不上锁的就是还活着的 codex 进程,现在是 0 个。临时目录在快照前一周冒过一波,快照前两天以后就没有新的了。

codex 临时目录,每天新建多少个

按目录时间,快照前 19 天到快照当天;活着的 codex 进程:0

以后怎么看登录节点的负载

登录节点上能看 CPU、内存和会话记录;计算节点上只能看到 Slurm 的分配。下面的命令都是只读的。

# 登录节点:一条 ssh 抓全量快照(在计算节点上运行,脚本走 stdin)
ssh -o BatchMode=yes -o ConnectTimeout=180 <登录节点> 'bash -s' < snapshot.sh

# 按账号排:进程数、D 状态数、内存 GiB
ps -e -o uid=,stat=,rss= | awk '{n[$1]++; if($2~/^D/)d[$1]++; m[$1]+=$3} END{for(u in n) printf "%s %d %d %.2f\n",u,n[u],d[u],m[u]/1048576}' | sort -k4 -rn | head

# 按账号数会话记录
grep -h '^UID=' /run/systemd/sessions/* | sort | uniq -c | sort -rn | head

# 瞬时 CPU:取 top 的第二轮
top -b -n 2 -d 2 | awk '/^top -/{n++} n==2' | head -30

# 全集群谁拿着多少 GPU(只有分配,看不到利用率)
squeue -t R -h -o "%u %b" | awk 'match($2,/gpu:[a-z0-9_]+:[0-9]+/){split(substr($2,RSTART,RLENGTH),a,":"); g[$1" "a[2]]+=a[3]} END{for(k in g) print g[k], k}' | sort -rn | head

# 某个节点的 CPU 负载、剩余内存、已分配资源
scontrol show node <节点> | grep -oE '(CPULoad|AllocTRES|FreeMem)=[^ ]+'

# codex 在不在泄漏(任意计算节点,不用登录)
cd ~/.codex/tmp/arg0; a=0; for f in */.lock; do [ -e "$f" ] || continue; flock -n "$f" true 2>/dev/null || a=$((a+1)); done; echo $a

# 自己 job 里的 GPU 利用率(从别的 job 里跑要加 --export=ALL)
srun --export=ALL --jobid=<自己的 job> --overlap nvidia-smi

踩过的坑