博客 > 硬件&操作系统&网络&DevOps > Linux
# Linux连接到图形界面的方案 1. ToDesk或者其他远程连接工具,可以直接连接到控制台桌面。这个不多说了,但是要注意运行在不同X桌面上的ToDesk间不互通,不等同于多屏幕,一次只能在一个桌面启动ToDesk,多个会冲突。 2. 通过VNC或者RDP来连接。VNC连接有两种方案,一种是通过`x11vnc`转发已经开启的控制台桌面或虚拟桌面,另一种是通过`TigerVNC`/`TightVNC`等工具直接call一个`vncserver`命令,同时完成开启桌面和开启服务器。而RDP连接使用的是`xrdp`,有很多配置(兼容xvnc,但是既然使用了`xrdp`,就没有必要再手动配置VNC服务器了,而是应该使用`xrdp`自动提供的更好的GUI方式:`xorg`)。 3. 最推荐的方式是使用RDP,因为比VNC实在是少卡顿太多了,而且还是Windows自家的远程方案,Windows自带客户端。 ## RDP方案 这里以Fluxbox为例,也可以使用其他的WM/DE。首先安装: ```sh sudo apt install -y xrdp xorgxrdp fluxbox sudo systemctl enable xrdp --now ``` 配置一个`~/.xsession`: ``` picom & exec fluxbox ``` 然后`chmod +x ~/.xsession` 然后可以从`/etc/xrdp/xrdp.ini`里更改一下RDP端口,然后把该文件末尾除了xorg之外的session type(如xvnc/vnc-any)全部注释。 配置结束后,重启服务: ``` sudo systemctl restart xrdp ``` 之后就可以在Windows上直接运行命令`mstsc`来连接咯! ## VNC方案 ### 方案一:转发控制台桌面 这种方法的核心是“所见即所得”,你看到的远程桌面,就是连接在物理显示器上图形界面,与ToDesk一致。当然,也可以通过`Xvfb`来创建虚拟桌面,然后转发它。 `x11vnc`作为一个轻量级的程序,连接到已经存在的X服务器会话。它像一个“中间人”,截获该X会话的所有图形变化,然后通过VNC协议将其广播给客户端。它不创建新的桌面,仅仅是分享已有的。 ``` # 安装 sudo apt install x11vnc # 设置密码 x11vnc -storepasswd sudo cp ~/.vnc/passwd /etc/x11vnc.passwd sudo chmod 600 /etc/x11vnc.passwd # 手动启动 # -display :0 -> 指定要共享的X会话 # -forever -> 允许多个客户端连接,一个断开后不退出 # -pwfile -> 指定密码文件 # -rfbport 5900 -> 指定VNC监听端口 (默认) # -bg -> 后台运行 x11vnc -display :0 -forever -pwfile /etc/x11vnc.passwd -rfbport 5900 -bg ``` 为了让`x11vnc`开机自启,建议配置成systemd服务。 创建服务文件`/etc/systemd/system/x11vnc.service`: ``` [Unit] Description=Start x11vnc at startup. After=graphical.target [Service] Type=simple ExecStart=/usr/bin/x11vnc -display :0 -forever -pwfile /etc/x11vnc.passwd -rfbport 5900 ExecStop=/usr/bin/pkill x11vnc Restart=on-failure User=root # 注意权限,可能需要根据实际情况调整 [Install] WantedBy=multi-user.target ``` 启用并启动: ``` sudo systemctl enable x11vnc.service sudo systemctl start x11vnc.service ``` 另外可以补充一下,`Xvfb`是一个用来生成虚拟桌面(但不带任何会话,也不带VNCServer)的指令,有了`Xvfb`后可以使用`env DISPLAY=:<DISPLAY_NO> <某个GUI程序>`的方法来在该X会话中启动一个图形程序,这时`x11vnc`就可以转发了,用法如下: ``` Xvfb :3 -screen 0 2560x1440x24 -dpi 144 -ac -nolisten tcp +extension GLX +render -noreset ``` `:3`是示意,可以是任何未占用的`DISPLAY`编号。`-screen <number>`可以有多个,每个都可以有分辨率、色深、DPI。其他参数不建议改。 但是警惕,在此虚拟桌面中,硬件图形加速是不可用的。所有图形渲染都由CPU完成(通过`+extension GLX`参数支持OpenGL在CPU上运行),无法胜任高负载的3D渲染、游戏或视频流处理任务。 为了把空屏占满,我们可以启动一个极简WM: ``` DISPLAY=:3 startfluxbox ``` 然后转发并连接: ``` x11vnc -display :3 -forever -usepw -rfbport 5903 -repeat -wait 5 -defer 5 -bg ``` ### 方案二:创建虚拟桌面 这种方法是完全独立的。它会在后台创建一个全新的、纯内存的虚拟显示环境,你可以在里面启动一个完整的桌面环境(如XFCE/LXDE等)。 VNCServer可以看作是`Xvbf`和`x11vnc`和一个启动脚本(如WM或DE)的组合。 安装:选择`tigervnc`或`tightvnc`。注意这和客户端的`vncviewer`无需相同。客户端只有`tightvnc`比较好用,`tigervnc`不支持Hi-DPI。服务器上两个都可以用。 设置密码:每个用户第一次启动VNC服务前,都需要为自己设置一个密码。这个密码是针对用户的,存储在用户的 `~/.vnc/` 目录下。 ``` vncpasswd ``` 配置启动脚本:`vi ~/.vnc/xstartup`。这里使用最轻量但是还算能用的桌面环境LXDE(需要提前安装): ``` #!/bin/bash lxterminal & /usr/bin/lxsession -s LXDE & ``` 然后: ``` chmod +x ~/.vnc/xstartup ``` 启动: ``` # 启动编号为 :1 的虚拟桌面 (客户端连接端口为 5900 + 1 = 5901) # -geometry 2560x1440 -> 可在此指定分辨率 # -dpi -> 可在此指定DPI vncserver :1 -geometry 2560x1440 -dpi 120 # 列出当前运行的VNC会话 vncserver -list # 停止编号为 :1 的虚拟桌面 vncserver -kill :1 ``` 每次都输入参数很麻烦。你可以为 TigerVNC 创建一个用户配置文件,让设置永久生效。 编辑或创建 `~/.vnc/config` 文件: ``` # VNC服务器默认配置 geometry=2560x1440 dpi=120 # 你还可以添加其他参数,如: # localhost=yes # 只允许从本地(通过SSH隧道)连接,更安全 ``` 保存后,下次直接运行 `vncserver :1` 就会自动应用这个配置。 ## 一些方便使用的小技巧 ### 中文环境和中文输入法 首先安装中文字体并刷新系统记录: ```sh sudo apt install -y fonts-noto-cjk fc-cache -fv ``` 接下来是中文输入法fcitx5: ```sh sudo apt install -y fcitx5 fcitx5-chinese-addons fcitx5-rime ``` 然后,在xsession中(或者手动启动): ``` export GTK_IM_MODULE=fcitx export QT_IM_MODULE=fcitx export XMODIFIERS=@im=fcitx export SDL_IM_MODULE=fcitx export LANG=zh_CN.UTF-8 export LC_COLLATE=C fcitx5 -d & # ... 其他 ``` 然后,第一次运行时,应该配置一下,运行`fcitx5-configtool`,在里面配置需要的东西。注意默认不会给每个程序打开输入法,Ctrl+Space才会打开,然后Shift是切换中英文,这个也可以配置为自动打开,具体请到GUI配置界面自己摸索。 所有需要输入法的程序都必须在fcitx5运行以后再启动,之前启动的无法使用输入法。 ### 仅开放SSH端口进行连接的方法 这是一种推荐的方法,能够避免远程连接易被攻击带来的风险。同时也是一种部署友好的方法,避免在防火墙中添加无必要的端口放行规则。 在客户端机器上打开SSH转发: ``` ssh -L xxxx:localhost:yyyy -c [email protected] -m [email protected] -x -a -o "IPQoS=lowdelay" -o "Compression=no" -N remote_user@remote_host # ssh -L # SSH Local Port Forwarding # <local port>:<forwarding host relative to remote>:<forwarding port relative to remote> # -N # no interactive terminal # <remote user>@<remote host> ``` 这里`yyyy`代表远端机器上VNC或RDP服务器的端口,`xxxx`是要映射到的本地端口,也是本地的mstsc或vncviewer最终要连接的端口,而要连接的主机名始终为本机localhost。 ### 临时更改分辨率(仅VNC) 虽然`Xvfb`和`vncserver`都有直接指定geometry和DPI的参数,但是都不像服务器端物理控制台里的DE一样,可以动态设置这些参数。因此,需要一种能动态设置参数的方法,也就是`xrandr`。 而RDP是受客户端分辨率控制的,并不是服务器端主动控制,因此无需考虑这个环节。 首先,不带参数运行`xrandr`得到当前屏幕和显示器参数: ``` xrandr ``` 如果有显示器,应该会展示出来其名称及可用分辨率,同时还有屏幕(Screen)的信息。如果是纯虚拟桌面,显示器名称应该叫类似于`screen`或者`default`或者带`VNC`字样的名字。`xrandr`的输出形式类似于: ``` Screen 0: minimum 32 x 32, current 2560 x 1440, maximum 32767 x 32767 <显示器名称> connected 2560x1440+0+0 0mm x 0mm 2560x1440 60.00*+ 1920x1080 60.00 ``` 由于我们主要讨论`Xvfb`和`vncserver`创建出的虚拟桌面,对于物理屏幕的操作更简单傻瓜,因此我们只在最后附上更改物理屏幕的方法,而先介绍虚拟桌面需要的操作。 ``` # 获取一个mode标准 cvt 1920 1080 # 返回应类似: # Modeline "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync # 给xrandr添加mode,--newmode后跟cvt返回的Modeline之后一串(注意不包含单词Modeline) xrandr --newmode <cvt返回值> # 将此模式赋予当前显示器 xrandr --addmode <显示器名称> "1920x1080_60.00" # 将当前显示器更改为此模式 xrandr --output <显示器名称> --mode "1920x1080_60.00" ``` 而物理显示器一般直接使用支持的分辨率和刷新率就好了: ``` xrandr --output <显示器名称> --mode <运行无参xrandr列出的模式之一> ```