1. 先说结论:这趟 xrdp 的坑,值得记录
最近在一台 Arch Linux 上折腾 xrdp,目标特别朴素:局域网里的另一台电脑能直接远程登录图形桌面,不要每次有事都跑机房。结果这个看起来常规的活儿,硬生生把我从客户端连上就闪退,熬到黑屏,再到蓝屏,三种最难看的画面全见了一遍。xrdp 本身不复杂,但配合 Arch 的滚动更新、桌面环境的启动方式、隐藏的 D-Bus 会话总线,任何一个环节没对齐,都会变成远程桌面起不来的惨案。这篇记录想把这次的完整排查过程、最终能稳定复现的配置,以及踩坑后的判断思路都留下来,给准备在 Arch 上使用 xrdp 的朋友参考。
先说结论,后面所有细节都是围绕这个结论展开的:xrdp 的故障,绝大多数不是 xrdp 本体坏了,而是会话启动链路断了。完整链路是客户端 -> xrdp 主服务 -> xrdp-sesman -> Xorg + xorgxrdp -> startwm.sh -> 桌面环境。链路中每一环都有自己的日志,闪退、黑屏、蓝屏分别对应着不同环节出问题。因此排查时不要盯着客户端界面发呆,也不要急着重装桌面环境,应当沿着链路一层层看日志、确认进程、验证配置。
1.1 三种典型故障现象
我在这台机器上实际遇到的现象可以归纳成三类,你遇到的问题大概率也逃不出这三个分类:
- 闪退:客户端输入账号密码后,画面只出现几秒钟就断开,直接回到登录窗口。这类问题最折磨人,因为日志里信息很多,但真正有用的报错往往藏在后面。
- 黑屏:客户端能连上,RDP 窗口也打开了,但整个桌面区域是黑色或灰色,鼠标要么不动,要么能动但没法点击。这说明 X 服务起来了,但桌面环境没有接管屏幕。
- 蓝屏:这里说的不是系统崩溃的蓝屏,而是 xrdp 自己绘制的一个蓝色错误页,上面会写类似“Failed to create session”的文字。这个页面反而是最好判断的,因为它的意思是会话创建阶段就失败了,问题通常出在服务状态、Xorg 模块或者基础权限上。
1.2 推荐的排查顺序
我的排查顺序是固定的:先看日志,再确认启动脚本,最后才碰桌面环境和 D-Bus。日志能告诉你 80% 的真相,不要用猜的。比如闪退时,/var/log/xrdp-sesman.log里通常会直接写出 Xorg 启动失败的原因;黑屏时,~/.xsession-errors里往往写着“Failed to connect to bus”之类的字眼;蓝屏时,/var/log/xrdp.log会告诉你 sesman 是否可用。
确认完日志后,再回过头检查/etc/xrdp/startwm.sh。这个脚本是 xrdp 会话跟桌面环境之间的桥梁,很多闪退和黑屏都是因为它没有正确执行桌面程序导致的。我把 startwm.sh 改成用dbus-run-session包一层之后,问题基本就解决了。最后,如果日志和脚本都正常,才需要考虑是不是桌面环境本身与 xrdp 不兼容,比如 GNOME 在高版本 Arch 上对 Xorg 会话支持不佳,这类问题靠改配置很难根治,换一个更纯正的 X11 桌面反而是最快路径。
2. 安装环节:Arch 上装 xrdp 的正确姿势
安装这一步本身不难,但很多人从第一步就埋下了坑:只装了xrdp,没装xorgxrdp,或者装了之后没有确认服务状态,导致后续排查方向整个跑偏。这里把安装、启动、验证三步完整过一遍。
2.1 安装 xrdp 与 xorgxrdp
在 Arch Linux 上安装 xrdp 很简单:
sudo pacman -S xrdp xorgxrdp需要特别注意xorgxrdp这个包。xrdp 本身是 RDP 协议的服务器端,负责监听 3389 端口、处理客户端连接和 RDP 协议解析,但它并不直接提供图形输出。真正干活的 Xorg 服务器需要知道如何把 xrdp 传来的画面渲染出来,这一层就是xorgxrdp完成的。它本质上是一个 Xorg 模块,会把 RDP 客户端的屏幕当成一个虚拟显示器,同时把鼠标键盘事件转发进去。没有它,Xorg 启动时根本加载不到对应的驱动,远程桌面要么直接失败,要么就是黑屏。
我见过有人只装 xrdp 之后连接,客户端一直卡在登录界面,日志里反复出现module load xorgxrdp failed,这就是缺包导致的。所以安装完以后建议先确认:
pacman -Q xrdp xorgxrdp两个包的版本都在,再进行下一步。
2.2 启动服务并验证端口
安装完成后启动服务:
sudo systemctl enable --now xrdp sudo systemctl enable --now xrdp-sesman这里建议把xrdp-sesman也单独确认一下。虽然 xrdp 主服务通常会自动拉起它,但我遇到过主服务起来了、sesman 却没有正常启动的情况,结果客户端连接时直接蓝屏,日志里提示无法连接会话管理服务。两个服务都确认一遍最稳妥:
systemctl status xrdp xrdp-sesman ss -tlnp | grep 3389如果看到0.0.0.0:3389在监听,说明服务层没问题。Arch 默认不像某些发行版会启用复杂防火墙,但如果你的机器上配置了 nftables 或者 iptables,需要在规则里放行 3389 端口,否则客户端永远连不上,这个问题跟 xrdp 本身无关。
2.3 startwm.sh 决定会话入口
xrdp 每次建立会话时,会调用/etc/xrdp/startwm.sh来启动用户的桌面环境。这个脚本的位置和权限都很关键,建议安装后先检查:
ls -l /etc/xrdp/startwm.sh正常情况下它应该是可执行的。Arch 自带的默认版本会尝试加载/etc/X11/xinit/xinitrc或用户家目录下的~/.xinitrc,并把启动结果传递出去。问题在于,如果用户没有配置~/.xinitrc,或者xinitrc里没有明确执行桌面会话,那么脚本运行完可能就什么都没启动,会话变成空壳,表现出来就是闪退或黑屏。
我建议不要依赖默认行为,直接把这个脚本改成明确的启动命令。这种做法最稳,因为不依赖用户的~/.xinitrc是否存在。后面第五节会给出完整配置。改完脚本后注意换行符必须是 LF,不要用 Windows 编辑器保存成 CRLF,否则 bash 执行时会报$'\r': command not found,这也是一种很隐蔽的闪退原因。
3. 闪退:连接成功却瞬间断开
闪退是最让人烦躁的故障,因为从用户体验看就是“连上了又掉了”,很容易让人怀疑是网络或者客户端问题。实际上大部分闪退都跟网络无关,而是会话进程自己退出了。定位闪退,必须靠日志。
3.1 先看日志,不瞎猜
xrdp 的日志分布在三个地方,排查时最好三个都看:
| 日志文件 | 作用 |
|---|---|
/var/log/xrdp.log | 主服务日志,记录客户端连接、会话建立、登出、错误码 |
/var/log/xrdp-sesman.log | 会话管理日志,记录 Xorg 的启动命令、会话分配、崩溃原因 |
~/.xsession-errors | 用户会话内部日志,记录桌面环境启动时的输出和报错 |
排查闪退时,我一般同时开两个终端窗口,一边连接客户端,一边实时跟踪日志:
sudo tail -f /var/log/xrdp-sesman.log tail -f ~/.xsession-errors“闪退”瞬间,日志里通常会出现三样东西:Xorg进程退出、startwm.sh调用完成后没有子进程、或者某个error级提示。有一次我的日志里明确写着No session leader,这其实就是 startwm.sh 执行完exit之后,没有留下桌面进程导致的。
3.2 常见根因逐个排除
闪退的常见根因,按我遇到过的频率排序如下:
第一是 startwm.sh 没有正确 exec 桌面程序。如果脚本里只写了启动命令但没加exec,桌面环境会在一个子 shell 里运行,一旦 startwm.sh 本身执行结束,子 shell 被回收,整个会话就断了。所以关键命令必须写成exec dbus-run-session -- startxfce4这种形式,让启动进程替换掉当前 shell。
第二是用户 shell 配置文件里有问题。xrdp 登录后不经过显示管理器,它会作为一个登录 shell 去加载用户的~/.profile、~/.bash_profile。如果这些文件里有输出乱码、有错误路径、甚至执行了会退出的脚本,都会导致会话连环退出。遇到这种情况,可以用临时用户测试,或者把~/.bash_profile里的内容注释掉一部分再试。
第三是 Xorg 模块加载失败。日志里如果出现module load xorgxrdp failed或Failed to add module,就需要确认xorgxrdp是否安装,以及 Xorg 日志里有没有更具体的报错。Arch 的滚动更新偶尔会让 xorgxrdp 和 Xorg 版本不匹配,此时重装xorgxrdp通常能解决。
第四是权限问题。~/.Xauthority文件属主错误、/tmp/.X11-unix目录权限不对、用户家目录被设置了过严格的权限,都会导致 Xorg 无法写入或读取凭据。排查时检查用户是否能正常写家目录,ls -ld ~不能是000这种极端权限。
3.3 闪退和黑屏、蓝屏怎么区分
闪退、黑屏、蓝屏虽然都让人头疼,但对应的问题阶段不同,判断方法也很简单:看连接后进程是否还活着。闪退时,进程整个消失,ps -ef | grep Xorg看不到对应的 Xorg 进程;黑屏时,Xorg 进程还在,但在桌面进程列表里找不到窗口管理器;蓝屏时,Xorg 可能根本没启动,客户端直接看到了 xrdp 的错误绘制页。这个区分很重要,因为接下来的排查方向完全不一样。
4. 黑屏与蓝屏:最典型的两类会话失败
如果说闪退是“断”,黑屏和蓝屏就是“卡住”。黑屏代表已经进入会话但显示内容为空,蓝屏代表会话创建失败。两者的原因和解决方式差别很大,需要分开讲。
4.1 黑屏:桌面 Shell 没接管
黑屏的实质是 Xorg 已经起来了,远程桌面也有了显示输出,但没有任何窗口管理器或桌面面板去绘制界面。你可以把它理解成 X 服务器是一块画布,画布挂在墙上了,但画布上什么都没画。xrdp 本身不负责画桌面,它只负责把 X 的显示内容传给客户端,所以桌面必须由xfce4-session、gnome-session这类程序来“画”。
判断黑屏最直接的方法是登录后执行:
ps -ef | grep -E 'Xorg|xfce|gnome|plasma'如果输出里只有Xorg,没有xfce4-session或xfwm4,那就说明 startwm.sh 没有把桌面环境启动起来。这时候不要怀疑 xrdp 设置,问题几乎都在启动脚本上。最常见的情况是~/.xinitrc为空、内容注释掉了、或者 startwm.sh 调用的是exec xterm这类一次性程序,窗口一关,桌面就没了。
Black screen 还有个容易忽略的帮凶:D-Bus。很多桌面组件在启动时会检查DBUS_SESSION_BUS_ADDRESS环境变量,如果这个变量不存在或指向了一个已经失效的地址,它们会选择直接退出或静默失败,最终结果就是黑屏。这个问题在 xrdp 会话里特别典型,因为正常从显示管理器登录时,显示管理器会帮你拉起 session bus,而 xrdp 是“裸启动”桌面,没有人做这件事。
4.2 蓝屏:xrdp 自己的错误说明页
蓝屏不是 Arch 或 Xorg 的专利,而是 xrdp 客户端在会话创建失败时显示的一个错误页。背景是蓝色,中间有白色或黑色文字,通常会写Failed to create session或Error connecting to session manager。很多第一次遇到的人会以为系统崩了,其实它只是把失败的结论画在屏幕上给你看,真正的细节在服务端日志里。
蓝屏出现时,我建议立刻检查两个服务:
systemctl status xrdp-sesman sudo tail -n 50 /var/log/xrdp-sesman.log如果 sesman 服务异常,先重启再试。如果日志里显示Xorg启动失败,那就去看 Xorg 自己的日志。Xorg 日志的位置通常在~/.local/share/xorg/Xorg.0.log,找不到时也可以用find / -name 'Xorg.*.log'搜索。常见错误包括xorgxrdp模块缺失、显卡驱动冲突、/tmp/.X11-unix目录被错误清掉。另外还要确认/etc/xrdp/下有个rsa2048.pem之类的密钥文件,虽然 Arch 的包会默认生成,但如果你从老版本迁移而来,文件丢失就会造成会话初始化失败。
4.3 推荐用 XFCE 作为 xrdp 的默认会话
经过这次踩坑,我的最终建议是对 xrdp 使用 XFCE 作为默认桌面,而不是 GNOME。原因不是 XFCE 比 GNOME 漂亮,而是 xrdp 本质上工作在 Xorg 会话上,XFCE 对纯 X11 环境的依赖最少,启动速度也快。GNOME 在新版本里偏向 Wayland,Xorg 会话需要额外配置,在 xrdp 下黑屏和崩溃的概率极高。KDE Plasma 也能用,但依赖较重的合成器在远程场景下容易出问题。
在/etc/xrdp/startwm.sh中,最稳的启动写法是:
#!/bin/bash unset DBUS_SESSION_BUS_ADDRESS exec dbus-run-session -- startxfce4第一行unset是为了清掉从 xrdp 服务进程继承来的、可能有问题的 D-Bus 地址;第二行dbus-run-session会为远程会话创建一个全新的 session bus;exec则是让桌面进程接管当前 shell。这样写之后,黑屏概率会大幅下降。如果你本地已经装好了 XFCE,但连接时还是黑屏,也可以先手动验证一下 XFCE 能否正常启动:
dbus-run-session -- startxfce4在纯终端里跑这个命令如果能看到桌面组件启动,就说明环境本身没问题,问题只在于 xrdp 调用脚本的方式。
4.4 D-Bus 与 session bus 的细节
D-Bus 分 system bus 和 session bus 两级。system bus 由系统服务使用,session bus 则伴随用户会话存在。正常图形登录时,显示管理器会为每个会话初始化 session bus,设置DBUS_SESSION_BUS_ADDRESS环境变量。xrdp 的会话绕过显示管理器,如果没人设置这个变量,很多桌面组件会尝试自动启动一个 bus,但自动启动经常失败或产生多个相冲突的实例。
很多黑屏问题的日志里都可以看到Failed to connect to bus、Error: cannot open display、Unable to autolaunch a dbus-daemon without a $DISPLAY for X11之类的错误。解决办法就是用dbus-run-session显式包裹桌面进程。它会在前台启动一个临时 dbus-daemon,设置好环境变量后再执行后面的命令,命令退出时自动清掉 bus,正好适合 xrdp 这种“一次会话一个进程树”的模式。
如果你不想依赖 startwm.sh,也可以把export DBUS_SESSION_BUS_ADDRESS的地址用命令行参数拼出来,但那种写法太绕,兼容性也差。实际测试下来,dbus-run-session是最省心的方案,既不用手动管理 PID 和 socket 路径,也不会在用户注销后留下孤儿进程。
5. 实操汇总:一份可以直接抄的配置清单
前面讲了原理和坑,这一节把我在 Arch 上最终稳定运行的配置完整贴出来。照抄之后,绝大多数闪退、黑屏、蓝屏问题都能解决。
5.1 最小可用的 startwm.sh 与 .xinitrc
先看/etc/xrdp/startwm.sh:
#!/bin/bash # xrdp 会话入口,稳定版 unset DBUS_SESSION_BUS_ADDRESS exec dbus-run-session -- startxfce4保存后确认权限:
sudo chmod +x /etc/xrdp/startwm.sh同时把用户家目录的~/.xinitrc也统一起来,防止某些情况下本地 X 会话与远程会话行为不一致:
#!/bin/bash exec dbus-run-session -- startxfce4注意,~/.xinitrc不一定被 xrdp 直接读取,但保持一致可以减少排查时的干扰。改完之后重启服务:
sudo systemctl restart xrdp-sesman sudo systemctl restart xrdp然后重新连接测试。如果你的 Arch 上装了多个桌面环境,希望按用户区分,也可以在 startwm.sh 里用 case 判断登录用户名,但这不是必须的,先用最小配置跑通再说。
5.2 xrdp.ini 参数:颜色深度、压缩与加密
/etc/xrdp/xrdp.ini里有几个参数会直接影响连接体验和稳定性。我常用的是:
| 参数 | 推荐值 | 说明 |
|---|---|---|
max_bpp | 24 | 颜色深度,32 位看起来更细腻,但带宽占用和兼容性都更差 |
use_compression | yes | 启用 RDP 压缩,局域网内也能减少延迟 |
crypt_level | high | 加密级别,按安全需求调整,一般 high 足够 |
bitmap_cache | yes | 启用位图缓存,能明显降低重复画面传输 |
bitmap_compression | yes | 配合压缩机制,减少流量 |
如果你遇到远程画面一顿一顿的情况,建议先把max_bpp降到24,而不是急着调分辨率。很多时候 32 位色深会在某些虚拟显卡驱动下产生额外的内存压力和传输开销。分辨率一般在客户端连接时指定,xrdp 登录窗口上方可以选择大小;想要固定分辨率,可以在 startwm.sh 里加上xrandr --size 1920x1080,但前提是 Xorg 已经知道这个尺寸,否则这个命令会被忽略。
5.3 服务管理技巧
xrdp 的配置改动,并不是在客户端重连就能生效的。服务端需要重启对应服务,而且注意顺序:先xrdp-sesman,再xrdp。因为 xrdp 主服务启动时会去连接 sesman,如果 sesman 还没就绪,主服务会报错。
sudo systemctl restart xrdp-sesman sudo systemctl restart xrdp此外,xrdp 会话异常退出后,/tmp/.X11-unix/下可能会残留老的 socket 文件。如果下一次会话启动时发现 display 号冲突,就会出现连接成功后立刻闪退的情况。清理方法:
ls /tmp/.X11-unix/ sudo find /tmp/.X11-unix/ -type s -delete清理前确认没有本地正在运行的 X 会话,否则会把本地桌面也干掉。只远程办公的机器问题不大,但如果是双系统里还开着本地图形会话的机器,要格外小心。
6. 常见问题速查表:从现象直接到命令
最后把这次过程中收集到的故障现象、检查命令和处置方法整理成速查表,方便你遇到问题时直接对照。
6.1 症状定位速查表
| 症状 | 可能原因 | 检查命令 | 处理方法 |
|---|---|---|---|
| 连接后闪退 | startwm.sh 没有 exec 桌面进程 | sudo tail -n 30 /var/log/xrdp-sesman.log | 改成exec dbus-run-session -- startxfce4 |
| 闪退且日志有 shell 报错 | ~/.profile、~/.bash_profile有异常命令 | bash -x ~/.profile | 修复或临时注释可疑命令 |
| 黑屏但 Xorg 存在 | 桌面环境没有启动或 D-Bus 失败 | ps -ef | grep fce | 使用 XFCE 并配置 session bus |
| 黑屏且有 D-Bus 报错 | DBUS_SESSION_BUS_ADDRESS无效 | grep -i dbus ~/.xsession-errors | startwm.sh 加dbus-run-session |
| 蓝屏错误页 | sesman 未运行或 Xorg 模块缺失 | systemctl status xrdp-sesman | 重启服务,确认 xorgxrdp 已安装 |
| 鼠标能动但桌面没窗口 | 窗口管理器未启动 | ps -ef | grep xfwm4 | 启动 xfce4-session 或手动启动 xfwm4 |
| 远程画面卡顿 | 颜色深度过高或压缩未开 | 查看xrdp.ini的max_bpp | 降到 24,开启压缩 |
| 剪贴板无法复制粘贴 | chansrv异常 | grep -i chansrv /var/log/xrdp.log | 重启 xrdp 服务,检查 chansrv 进程 |
6.2 会话重置“三板斧”
当你已经改了配置但现象依旧,或者怀疑有残留进程时,建议按顺序做:
sudo systemctl restart xrdp-sesman sudo systemctl restart xrdp pkill -f Xorg这里 pkill Xorg 需要说明一下:它会把所有 Xorg 进程都杀掉,包括 xrdp 会话里的 Xorg,也包括本机图形界面。如果这台机器是专用远程服务器,杀掉没问题;如果它是你平时也在用的工作站,建议先通过who或w查看有没有本地登录会话,避免误杀。更稳妥的做法是只杀 xrdp 相关的 display,比如日志里明确是:10,就执行:
pkill -f "Xorg :10"杀掉之后,残留的 session socket 会释放,再次连接时 display 号重新分配,闪退和黑屏概率都会下降。
6.3 打开 debug 日志定位隐藏问题
如果正常日志信息量不够,可以临时打开 debug 日志。/etc/xrdp/xrdp.ini和/etc/xrdp/sesman.ini里都有日志级别配置,找到类似LogLevel=INFO的行,改成LogLevel=DEBUG,然后重启服务:
sudo sed -i 's/LogLevel=INFO/LogLevel=DEBUG/' /etc/xrdp/xrdp.ini sudo sed -i 's/LogLevel=INFO/LogLevel=DEBUG/' /etc/xrdp/sesman.ini sudo systemctl restart xrdp-sesman xrdpdebug 模式会输出非常多内容,排查完一定要改回 INFO 或重新配置,否则日志文件一天能涨几十 MB。排查时重点关注几个关键词:sesman、xorgxrdp、chansrv、failed、error。我这次就是靠 debug 日志里一行cannot open display :10才确认是 X 权限问题,而不是桌面环境的锅。
最后再分享一个实操中的心得:xrdp 这套东西,配置越简单越不容易出问题。很多人喜欢把 startwm.sh 写得又长又花,添加各种环境变量和用户判断,结果反而埋了雷。先用最保守的unset DBUS_SESSION_BUS_ADDRESS加exec dbus-run-session -- startxfce4跑通,再逐步加自己的需求,这样不仅问题容易定位,也方便以后回滚。折腾远程桌面的本质不是秀操作,而是让它在你要用的时候,真的能连上、能看见、能点得动。