前言
挺早之前就已经把主力机迁移到了一台 LG Gram 上,原来的厚砖游戏本已经变成了旁路由 + 编译服务器。Gram 虽然优雅,但是,某些开发任务在它上面完成还是有些吃力的,比如跑 Android Studio ,跑是能跑,但是当单文件代码行数达到 1500+ 的时候,自动补全就已经卡的不行了。
所以,有没有什么解决方案能够实现类似 Windows 的远程桌面,连接到 Linux 桌面环境下呢?
嗯,KDE 自带了一个 Krfb ,可以将当前会话以 VNC 的形式共享出去。但是,这东西糊就算了,静置不动的时候网速都能跑到 20Mbps+ 实在是让人无法接受。
于是,我看上了一个叫做 Xrdp 的东西,那就配配看吧。
先说说我的环境:ArchLinux + KDE Plasma 5 (X11)。
跑起来
其实,光是成功的连上并进入桌面就花费了一番力气。这个东西的文档并不算很齐全,而且 journalctl
打出来的日志也并不能很好的点明问题所在,实在是有些头疼。
首先,安装核心软件包:
yay -S xrdp
然后,安装 Xorg 后端:
(三选一即可)
yay -S xorgxrdp-glamor
(英特尔与 AMD 核显)yay -S xorgxrdp
(不使用显卡渲染,CPU 占用率会比较高)yay -S xorgxrdp-nvidia
(英伟达独显,没有测试过,可能需要根据安装时的提示修改配置文件)
接下来,在 /etc/X11/Xwrapper.config
中加入一行 allowed_users=anybody
(如果没有这个文件则手动创建一个)。
(不知道为什么,这个步骤没有出现在英文版的 arch wiki 中,但没有它远程桌面是起不来的)
再接下来,创建 ~/.xinitrc
,并写入 /usr/lib/plasma-dbus-run-session-if-needed startplasma-x11
。
(正常步骤应该是修改原有的 .xinitrc
,但是,再次,我压根就没有这个东西,于是手动创建一个)
启用服务,再重启一下系统:
sudo systemctl enable xrdp.service
sudo systemctl enable xrdp-sesman.service
sudo reboot
输入用户名,密码,Session 就选 Xorg ,登进去应该就能够看到桌面了...
花里胡哨的问题
Xrdp 的使用感受确实要比 VNC 好多了,但是小问题还是不少的。
无法弹出授权提示框
在 Xrdp 下,这个框框不会弹出,对应的操作也会被直接拒绝。
解决方案一:
此类授权是由 polkit 负责的,我们可以修改 polkit 的配置文件,干脆直接允许所有的授权请求,虽然这不干净而且有点危险,但也算是能用:
/etc/polkit-1/rules.d/49-nopasswd_global.rules
/* Allow members of the wheel group to execute any actions
* without password authentication, similar to "sudo NOPASSWD:"
*/
polkit.addRule(function(action, subject) {
if (subject.isInGroup("wheel")) {
return polkit.Result.YES;
}
});
解决方案二:
这种解决方案出现在了 arch wiki 上,我们需要编辑 /etc/pam.d/system-auth
并注释掉所有包含 systemd_home
的行。
类似于这样:
#%PAM-1.0
auth required pam_faillock.so preauth
# Optionally use requisite above if you do not want to prompt for the password
# on locked accounts.
#-auth [success=2 default=ignore] pam_systemd_home.so
auth [success=1 default=bad] pam_unix.so try_first_pass nullok
auth [default=die] pam_faillock.so authfail
auth optional pam_permit.so
auth required pam_env.so
auth required pam_faillock.so authsucc
# If you drop the above call to pam_faillock.so the lock will be done also
# on non-consecutive authentication failures.
#-account [success=1 default=ignore] pam_systemd_home.so
account required pam_unix.so
account optional pam_permit.so
account required pam_time.so
#-password [success=1 default=ignore] pam_systemd_home.so
password required pam_unix.so try_first_pass nullok shadow sha512
password optional pam_permit.so
#-session optional pam_systemd_home.so
session required pam_limits.so
session required pam_unix.so
session optional pam_permit.so
在这之后授权框能够正常弹出了,但是这种注释想必会破坏一些东西,具体可以在该 issue 中了解详情。
(发现这种方案结合下面的自动登录会导致远程会话黑屏)
外接设备权限问题
这个问题其实和 xrdp 没有直接的关系。
在物理机未登录时,无论是登录 xrdp 还是 ssh ,都无法使用一些外接设备,比如:
$ adb shell
adb: insufficient permissions for device
See [http://developer.android.com/tools/device.html] for more information
对于 adb 来说,解决方法很简单,以 root 身份重启 adb server 即可:
$ adb kill-server
$ sudo adb start-server
但是,像 Dolphin 里的 MTP 就没这么容易解决了,因为 Dolphin 不被允许使用 root 身份运行。
造成这个问题的原因在于 systemd-logind 提供了用于多人一机的功能 “seat” 。 seat 基于 udev 规则工作,可以将不同的设备分配给不同的 session 。
但遗憾的是,像 ssh,xrdp 这样的远程会话,并不能被绑定到默认的 seat0 ,于是在没有物理的会话登录时,xrdp 和 ssh 会话都没法直接正常使用这些设备。
可以使用 loginctl
命令来查看当前会话及其绑定的 seat :
$ loginctl
SESSION UID USER SEAT TTY
1 1000 libxzr seat0
我也尝试过在 xorg 的启动参数中指定 -seat seat0
来强行绑定,但很遗憾并没有效果,于是最终想出了一个肮脏的绕过方法:
这样,既可以保证物理机上一定有一个 seat0 的会话正在运行,维持这些外接设备的可访问性,又不至于让开机密码消失。虽然手段有些肮脏,但结果算是好的。
在 stackexchange 上也有关于为 ssh 会话绑定 seat 的问题,可是截止目前为止还没有有效的回复:
https://unix.stackexchange.com/questions/709837/how-to-attach-virtual-ssh-session-to-systemd-seat0
baloo_file_extr 高 CPU 占用
具体原因不太清楚,但确实是开始使用 xrdp 之后出现的。
症状为 baloo_file_extr
持续占用 CPU (+ PID 暴增,因为它好像在不断重启) ,同时伴有 systemd-coredump
的 CPU 占用以及 journalctl
中的 crashdump 刷屏。
初步判断为文件索引系统出现了奇怪的状况,解决方法为关闭文件索引并重启:
$ balooctl disable
$ sudo reboot
参考资料
https://alvin.red/2021/11/06/archlinux-xrdp/
https://wiki.archlinux.org/title/xrdp
https://wiki.archlinuxcn.org/zh-hans/Xrdp
https://wiki.archlinux.org/title/Polkit
https://wiki.archlinux.org/title/xorg_multiseat