[Linux 故障排查] 解决 “Failed to start VNC server” 及 VNC 僵尸进程清理全攻略
前言
在高性能计算(HPC)集群或 Linux 服务器上运行图形化作业(如 Abaqus、Ansys、IC 仿真)时,VNC 是必不可少的工具。但你是否遇到过任务刚提交就立刻失败,报错日志显示无法启动 VNC 服务?即使尝试使用命令清理,也提示找不到 PID 文件?
本文将还原一次真实的排查过程,从报错分析到手动清理,再到自动化脚本优化,彻底解决 VNC 端口冲突与僵尸进程问题。
1. 故障现象
在 Slurm 集群提交作业后,日志中出现以下报错:
Failed to start VNC server on cpu01 with display 1
All vnc attempts failed. Exiting.
clean vnc session
尝试在计算节点上使用标准命令清理会话,却提示 PID 文件丢失,无法自动清理:
[root@cpu01 ~]# vncserver -kill :1
WARNING: vncserver has been replaced by a systemd unit...
Can't find file /root/.vnc/cpu01:1.pid
You'll have to kill the Xvnc process manually
这意味着:虽然系统认为 Display :1 被占用了,但对应的管理文件(PID file)已经丢失,导致死锁。
2. 根因分析
出现此问题通常有以下两个原因:
- 僵尸进程(Zombie Process):上一次作业(可能很久以前)异常退出(如节点掉电、强制杀作业),导致
Xvnc进程没有被正常回收,一直驻留在内存中占用端口。 - 残留锁文件(Stale Lock Files):即使进程已经结束,Linux 的
/tmp目录下仍残留着 X11 的锁文件,导致新任务认为该“车位”(Display ID)仍被占用。
3. 手动修复步骤(三步法)
第一步:“照妖镜”——查找僵尸进程
标准清理命令失效时,必须手动查找占用的进程。使用以下命令:
ps -ef | grep Xvnc
输出示例:
testcase 41763 1 0 2025 ? 00:01:31 /usr/bin/Xvnc :1 ...
testcase 9974 1 0 2025 ? 00:01:01 /usr/bin/Xvnc :2 ...
分析:可以看到 PID
41763的进程占用了:1,且启动时间竟然是 2025年(老旧的僵尸进程)。这就是导致新任务无法启动的元凶。
第二步:强制击杀
找到占用端口的 PID 后,使用 kill -9 强行终止:
# 杀掉占用 :1 的进程
kill -9 41763
# 如果有其他陈旧进程(如 :2, :3),建议一并清理
kill -9 9974
第三步:清理“幽灵”锁文件(关键!)
这是最容易被忽略的一步。杀掉进程后,必须手动删除 /tmp 下的锁文件,否则新服务依然起不来。
针对 Display :1,执行:
# 删除 X Server 锁文件
rm -f /tmp/.X1-lock
# 删除 Unix 通信套接字
rm -f /tmp/.X11-unix/X1
(如果是 Display :2,则将文件名中的 1 改为 2,以此类推)
4. 进阶方案:脚本优化(解决并发冲突)
如果你的集群有多个作业同时运行,或者你不想每次都手动修修补补,建议优化作业启动脚本。
痛点
原脚本通常硬编码了使用 :1 号显示器:
# 错误示范
vncserver :1
当两个作业同时调度到同一节点,或者 :1 没清理干净时,作业必挂。
优化策略
让脚本自动寻找当前节点上空闲的 Display ID(从 1 到 50 循环检测),实现“即插即用”。
优化后的 Shell 函数片段
#!/bin/bash
# 动态寻找并启动 VNC 的函数
start_vnc_server() {
echo "Searching for available VNC Display ID..."
# 循环检测 Display :1 到 :50
for i in $(seq 1 50); do
# 1. 检查 TCP 端口 (5900+i) 是否被占用
if command -v ss >/dev/null 2>&1; then
ss -lnt | grep -q ":$((5900+i)) " && continue
else
netstat -ln | grep -q ":$((5900+i)) " && continue
fi
# 2. 检查 /tmp 下的锁文件是否存在
if [ -f "/tmp/.X${i}-lock" ] || [ -f "/tmp/.X11-unix/X${i}" ]; then
continue
fi
# 3. 尝试启动 VNC
echo "Trying Display :${i}..."
vncserver :${i} -geometry 1920x1080 > vnc_start.log 2>&1
# 4. 判断启动结果
if [ $? -eq 0 ]; then
SID=$i
echo "SUCCESS: VNC started on :${SID}"
return 0
else
# 启动失败可能是碰巧冲突,尝试清理残留锁文件供下次使用
rm -f "/tmp/.X${i}-lock" "/tmp/.X11-unix/X${i}" 2>/dev/null
fi
done
echo "ERROR: No available Display ID found!"
exit 1
}
# 调用函数
start_vnc_server
export DISPLAY=:${SID}
5. 总结
遇到 Failed to start VNC server 报错时,请按以下清单操作:
- 不要慌张:这通常是上一次任务清理不干净导致的。
- 手动三连:
ps -ef | grep Xvnc找 PID。kill -9 <PID>杀进程。rm -f /tmp/.X*-lock /tmp/.X11-unix/X*删锁文件(最重要)。
- 脚本改进:不要在脚本里写死
vncserver :1,改用循环检测空闲端口的逻辑,彻底告别端口冲突。

4万+

被折叠的 条评论
为什么被折叠?



