解决 “Failed to start VNC server” 及 VNC 僵尸进程清理

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

[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. 根因分析

出现此问题通常有以下两个原因:

  1. 僵尸进程(Zombie Process):上一次作业(可能很久以前)异常退出(如节点掉电、强制杀作业),导致 Xvnc 进程没有被正常回收,一直驻留在内存中占用端口。
  2. 残留锁文件(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 报错时,请按以下清单操作:

  1. 不要慌张:这通常是上一次任务清理不干净导致的。
  2. 手动三连
  • ps -ef | grep Xvnc 找 PID。
  • kill -9 <PID> 杀进程。
  • rm -f /tmp/.X*-lock /tmp/.X11-unix/X* 删锁文件(最重要)。
  1. 脚本改进:不要在脚本里写死 vncserver :1,改用循环检测空闲端口的逻辑,彻底告别端口冲突。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值