X持久化远程应用Xpra快速起步
Xpra是一个开源跨平台持久化远程显示服务器以及用于转发应用程序和桌面屏幕的客户端。
Xpra提供了远程访问独立应用或者完整桌面的能力。对于X11,它就好像X11的
screen
: 允许你在远程主机上运行程序,直接将程序显示在本地主机。这个功能和X11的服务器运行在本地,计算客户端运行在远程服务器上相同。但是,神奇的是,当你断开运行的程序,然后从客户端(可以是相同主机或不同主机)再次连接到远程服务器,所有的工作状态不会丢失。这就同时具备了X11的轻量级运行速度和VNC不丢失运行程序状态(随时可以继续)的优点,非常适合移动开发工作。
Xpra甚至可以转发所有桌面,从X11服务器,MS Windows或者Mac OS X。而且Xpra甚至可以转发声音,剪贴板和打印服务。
Xpra可以通过SSH访问,也可以使用或不使用SSL加密而仅使用密码保护的明文TCP连接。
Linux不同发行版都有二进制软件包可以使用,从
Xpra Linux Download
可以获得下载信息
xpra platforms
提供了各发行版支持情况:
Fedora 34+
CentOS / RHEL 8.x
Ubuntu: Bionic, Focal, Hirsute, Impish
Debian: Stretch, Buster, Bullseye, Bookworm, Sid
支持 x86_64 和 arm64
macOS 10.9 (v3.x) 和 10.12.x (v4.x)
以下案例是Ubuntu Bionic版本的安装:
# install https support for apt (which may be installed already):
sudo apt-get update
sudo apt-get install apt-transport-https
# add Xpra GPG key
wget -q https://xpra.org/gpg.asc -O- | sudo apt-key add -
# add Xpra repository
sudo add-apt-repository "deb https://xpra.org/ bionic main"
# install Xpra package
sudo apt-get update
sudo apt-get install xpra
可以看到服务运行监听端口是 14500:
CGroup: /system.slice/xpra.service
├─361123 /usr/libexec/platform-python /usr/bin/xpra proxy :14500 --daemon=no --tcp-auth=sys --ssl-cert=/etc/xpra/ssl-cert.pem --ssl=on --bind=none>
└─361148 /usr/bin/dbus-daemon --syslog-only --fork --print-pid 4 --print-address 6 --session
此时,这个远程服务器上运行的xterm就会直接映射显示到本地主机的X桌面上
另一种方式是将步骤分开执行,分别在服务器上启动xterm会话,然后在本地主机去连接远程服务器上已经启动的会话:
在远程服务器上启动程序:
xpra start :100 --start=xterm
聚合桌面应用(最佳方案)
通过将 心仪
的应用程序集中在某个桌面显示屏,例如 :7
,这样只需要一次 xpra
连接,就可以同时访问多个X程序,并且和本地桌面(例如macOS)完全融合。
启动xpra服务器使用显示屏 :7
xpra start :7
将firefox运行在xpra server中:
DISPLAY=:7 firefox
将rxvt运行在xpra server中:
DISPLAY=:7 rxvt
将 VS Code 运行在xpra server中:
DISPLAY=:7 code
聚合桌面应用(最佳方案-screen)
结合服务器端的screen程序,可以实现更为方便的启动程序。也就是只要在 DISPLAY=:7
中启动了 screen
程序,后续在 screen
中启动的应用都会自动连入 xpra
桌面,也就简化了启动命令
启动xpra服务器和screen会话,所有在screen中的应用程序都是使用X,将定向到xpra服务器:
xpra start :7 && DISPLAY=:7 screen -S xpra
集成ssh-key
我在 SSH ProxyCommand实现穿透主机访问后端服务器 结合使用了 ssh密钥 方式认证,通过 ssh-agent
来实现一次输入密钥密码就可以多次任意访问不同服务器上SSH服务。不过, xpra
默认没有使用本地 ssh 认证,也就是没有使用 ssh-agent
缓存的密钥。
要解决这个兼容性,即让 xpra
能够使用操作系统已经加载的 ssh-agent
中缓存的密钥,需要使用 --ssh=ssh
参数,也就是让xpra直接使用本地现有ssh。所以,客户端访问命令可以修订成:
xpra --ssh=ssh attach ssh://z-dev/7
注意,这里 z-dev
是使用了 私有云SSH访问 配置了 ~/.ssh/config
,已经启用了ssh的 ProxyCommand
直接TCP访问(不推荐)
如果内部网络非常安全,可以采用直接TCP访问,设置xpra直接监听TCP端口:
xpra start --start=xterm --bind-tcp=0.0.0.0:10000
然后客户端就直接访问TCP端口:
xpra attach tcp://SERVERHOST:10000/
如果要增加安全性,可以在服务器端启动时加上密码认证 --tcp-auth=file,filename=mypassword.txt
完整桌面转发
Xpra也支持将整个桌面输出,类似VNC访问。以下是启动fluxbox桌面方法:
xpra start-desktop --start-child=fluxbox
我使用 i3窗口管理器 桌面
可以考虑对Windows或macOS桌面进行转发,通过服务器运行Windows/macOS虚拟机,实现不占用本地资源,尽享服务器高性能计算。
克隆已经存在显示
Xpra的 shadow
方式可以用来访问已经存在的桌面:
xpra shadow ssh://SERVERHOST/
这样就可以看到远程桌面。默认是X11的会话 :0
或者 :1
。如果有多个会话,也可以指定访问桌面:
xpra shadow ssh://SERVERHOST/DISPLAY
默认Xpra可以转发声音、剪贴板和光标,就好像应用程序的窗口,不过这些功能也可以关闭但是保留剪贴同步,例如:
xpra shadow --no-printing --no-windows --no-speaker --no-cursors ssh://SERVERHOST/
甚至可以将打印机转发到另一个服务器上,只需要启动一个远程会话但是不启动应用程序,并确保打印机转发激活:
xpra shadow --no-windows --no-speaker --no-cursors ssh://SERVERHOST/ --printing=yes
现在的使用经验
最新的 xpra
for macOS已经非常稳定(如果配置正确),只需要执行:
xpra attach ssh://huatai@192.168.6.253/7
就可以连接上文在服务器端启动在 :7
显示桌面的 xpra
会话,无缝访问会话中所有启动的Linux服务器上的图形程序,并且融入到本地操作系统中,就像本地原生程序。
以前的使用经验
macOS早期旧版本xpra不能直接使用 xpra
命令行。提供的图形界面Xpra,理论上应该是SSH服务器的22端口,访问的xpra是 :100
,配置如下:
然而,本地却始终看不到 xterm 窗口弹出(服务器端已经如上文启动了 xpra start :100 --start=xterm
)
我测试了多次,发现直接通过TCP访问远程xpra直接启动绑定端口的xterm是正常的,看起来问题在于SSH端口转发。所以,我采用手工方式在本地发起ssh的端口访问。
修改 ~/.ssh/config
添加配置:
Host worker7-x
HostName 192.168.1.7
User huatai
LocalForward 1100 127.0.0.1:1100
然后本地执行 ssh worker7-x
登陆到远程服务器上,就开启了SSH端口转发。此时,访问本地127.0.0.1的1100端口,就相当于访问远程服务器 192.168.1.7 的 1100 端口。
在远程服务器上执行以下命令,将xpra启动的应用程序绑定到 1100 端口上:
xpra start --start=/opt/GoLand-2020.2.3/bin/goland.sh --bind-tcp=127.0.0.1:1100
本地启用Xpra客户端,设置TCP访问方式,直接访问本地回环地址 127.0.0.1
端口 1100
,由于本地已经做了SSH端口转发,就可以直接访问远程服务器Xpra运行的X应用程序:
你没有看错,你可以在服务器上运行任何X程序,包括非常消耗计算资源的开发IDE,Jetbrains全家桶。我这里的案例就是在远程服务器上开发Go程序,无论何时何地,随时可以连接到服务器上,利用服务器强大的计算资源进行开发。
可以在服务器上运行多个大型程序,只需要使用不同端口运行,后续客户端通过SSH访问服务器端口转发到不同端口,就可以同时做很多计算密集型工作。
需要注意的是,所有启动 xpra
服务端命令都只能绑定 127.0.0.1
本地回环地址,避免端口暴露。所有访问都必须通过SSH加密,避免安全隐患。
目前还有一点遗憾是尚未设置好高分辨率,因为本地是MacBook Pro高清屏幕,远程映射过来的分辨率略低,字体不够清晰锐利。这个问题应该是服务器端显卡问题,我觉得后续可以通过 NVIDIA Virtual GPU (vGPU) 方式,在虚拟机中通过注入 NVIDIA 高性能显卡来实现性能提升。
运行 VS Code GoLand等工具:
xpra start --start=/opt/GoLand-2020.2.3/bin/goland.sh --bind-tcp=127.0.0.1:1100
xpra start --start=code --bind-tcp=127.0.0.1:1110
z-dev环境
在host主机 zcloud
上执行iptables端口转发:
iptables -A PREROUTING -t nat -i eno49 -p tcp --dport 25322 -j DNAT --to 192.168.6.253:22
iptables -A FORWARD -p tcp -d 192.168.6.253 --dport 22 -j ACCEPT
这里执行端口转发是因为通过 zcloud
对外网络接口能够转发到内部局域网的 z-dev
虚拟机上端口,如果客户端和服务器处于相同内网可以忽略这步
推荐采用单个xpra会话
我在 Fedora开发环境初始化 完整部署了一个支持中文输入的 xpra
会话,可以在Linux服务器上运行大量高资源消耗的图形程序,同时可以使用非常简单的瘦客户端进行连接(实际上还支持浏览器访问桌面的方式,甚至不需要客户端)。
单独的连接端口方式(已不使用)
在 私有云架构 的 z-dev
虚拟机中运行Fedora 35,安装 xpra
,并启动对应服务程序:
xpra start :100 --start=rxvt-unicode
xpra start :101 --start=firefox
对应客户端连接: