Linux 下可用的图形界面远程控制软件很多,滇狐很久以前写过的一个 Linux 下远程控制简介,感兴趣的可以简要了解一下。NoMachine 是 Linux 下实现远程桌面的另一个非常方便的软件,本文记录了在 Debian/Ubuntu 下安装和使用 NoMachine 的一些注意事项。

1 NX 的优点

NX 的原理和 VNC 很接近,同样也是通过在远程机器上虚拟一个 Xserver 的方式,将远程的应用程序绘制的图像都绘到虚拟的 Xserver 上,再通过 NX 协议将图像发送到客户端来,并接受客户端的键盘和鼠标事件。和 VNC 比起来,NX 主要有以下几大优点:

首先是速度,NX 协议允许对传输的图像进行压缩,在网络带宽有限的情况下,NX 可以动态地牺牲部分图像质量,获得更流畅的操作效果,而 VNC 受协议限制,无法做这样的动态有损压缩。

其次是安全性,VNC 使用自己单独的端口,使用自己定义的协议来传输数据,并且具有自己的一套密码认证方案,因此安全性完全取决于它自身实现的健壮性。NX 使用的是系统 SSH 协议,没有自己单独的一套身份验证机制,因此安全性完全依赖于系统 SSH 的安全性,不会引入新的安全隐患。

最后是其它服务的转发。NX 内置了对于文件共享、打印机共享以及本地声音系统共享的转发机制,连接到远程系统的时候可以非常方便地使用本地的资源。VNC 本身是不支持这些操作的,虽然对于高级用户而言,通过各种辅助软件和精妙的配置,以上功能都能实现,但毕竟不如 NX 这样本身内置了全部支持来得方便。

2 安装指南

NX 的安装很简单,直接到 NX 的官方网站去,找到适合自己平台的安装包,直接安装就可以了。对于客户端而言,只需要装 nxclient 就行了。对于服务端而言,需要同时安装 nxclient、nxnode 和 nxserver,由于服务端的程序用到了客户端的库,因此安装服务端的时候,必须先在服务端也安装一份客户端才行。安装完毕之后服务端会自动启动,如果没有什么高级需求的话,不需要对服务端进行什么特殊配置。

3 设置分辨率

我们这里说的“分辨率”,指的是 resolution,即“每英寸对应多少个像素”(DPI),不是 geometry,即“屏幕宽度和高度分别是多少像素”。Geometry 在 NX 登录的时候可以直接在客户端设置,登录之后也可以通过拖拽 NX 的窗口进行调节,不需要通过特殊的设置实现。

NX 默认的分辨率是 75dpi,由于 KDE 和 GNOME 程序都能强制 override 系统分辨率,将默认分辨率设置为 96dpi,因此对于 KDE 和 GNOME 程序而言,系统分辨率不正确并没有太大问题。但系统里毕竟还是有一些特殊的程序是不考虑 KDE 和 GNOME 的分辨率设置,直接使用系统分辨率的。

修改 NX 分辨率的方式是,到 NX 的安装路径下,找到 etc 目录 之下的 node.cfg,在文件中查找 AgentExtraOptions 字样,如果这个单词在该文件里完全不存在,则直接在文件尾部添加:

AgentExtraOptions = "-dpi 96"

如果 AgentExtraOptions 已经存在的话,则在原有的 AgentExtraOptions = "..." 的后引号前面加一个空格,补上 -dpi 96,譬如如果原先内容是:

AgentExtraOptions = "-nolisten tcp"

则改为:

AgentExtraOptions = "-nolisten tcp -dpi 96"

4 远程声音配置

Linux 下的声音系统极其混乱,导致在 Linux 下想要让系统正常发声,往往需要很费一番周折。在 NX 下的远程声音效果并不好,延时很严重,而且音质非常糟糕,配置远程声音的主要目的是方便播放一些提示音来监听工作状态,譬如滇狐喜欢在编译的时候设置编译完成后播放一段提示音,这样在 NX 里编译的时候就可以切换到本地玩一些别的事情了。

4.1 客户端

NX 在远程播放声音的时候,是通过把远程的数据转发到本地的一个 EsounD 服务器上实现的,因此,它必须现在本地启动一个 ESD。在 NX 的安装包里,提供了一个 NX 实现的 ESD,叫 nxesd,就在 NX 安装目录的 bin 底下。

然而,这个声音服务器直接通过 OSS 接口和声卡打交道,和本地已有的别的声音服务器并不能和睦相处。为了保证这个不听话的 nxesd 运行正常,我们需要通过本地声音服务器提供的 OSS wrapper 来启动它的声音服务器:如果本地的声音系统是 artsd,则使用 artdsp 作为 wrapper;如果本地的声音系统是 ESD,则使用 esddsp 作为 wrapper;如果本地的声音系统是 alsa,则使用 aoss 作为 wrapper;如果本地的声音系统是 pulseaudio,则使用 padsp 作为 wrapper;如果本地的声音系统不在上面列出的范围里,请自行查找相应的 wrapper 程序。

由于 nxclient 在启动的时候会自动调用 nxesd,因此,为了将我们的 wrapper 添加进去,我们需要先把 nxesd 改个名,让 nxclient 无法直接调用到它:

sudo mv nxesd nxesd.bin

然后,我们创建一个脚本,命名为 nxesd,并且给它加上可执行属性。这样,nxclient 在调用 nxesd 的时候,调用到的就是我们编写的脚本了,脚本内容如下:

#!/bin/sh

# Replace "padsp" below to your actual OSS wrapper
exec padsp /usr/NX/bin/nxesd.bin "$@"

记得将其中的 padsp 替换为你真实的 OSS wrapper 程序,并将 /usr/NX/ 替换为你真实的 NX 安装路径。

4.2 服务端

NX 在服务端会虚拟出一个 ESD 服务器来,因此,我们需要将所有支持 ESD 的程序设置为通过 ESD 来发声。

KDE 系统设置里的“多媒体”中能够直接识别出“Esound (ESD)”,直接将该选项提到设备列表的最前方即可。

GNOME 默认就是支持 ESD 的,无须进行特别配置。但 GNOME 下还有很多程序是通过 GStreamer 来发声的,因此我们需要对 GStreamer 作一些配置。运行 gstreamer-properties,在“音频”的“Default Output”下拉框中选择:“ESD - Enlightenment 声音守护程序”即可。至于“Default Input”,随便选一个就行,譬如“静音”,不会有人想用远程的服务器来录音的。

配置了 KDE 和 GNOME 的声音环境之后,绝大部分程序应该就可以正常发声了。还有一个最棘手的,就是网页里的 Flash。虽然我们不会在服务器上看网络视频,但能听到网络聊天程序通过 Flash 发出的提示音也是很重要的事情。Flash 发声是通过 alsa 接口进行的,并且无法配置成别的接口。因此,为了让 Flash 能发声,我们必须在远程包装一个 alsa。

ESD 是无法被直接包装成 alsa 的,但我们可以先把 ESD 包装成 PulseAudio,然后再把 PulseAudio 包装成 alsa,这样 Flash 就能正常播放了。

首先,我们将 ESD 包装成 PulseAudio,要做到这点,我们需要启动一个 PulseAudio 服务器,使用 ESD 作为 PulseAudio 服务器的输出接口。由于 NX 模拟的 ESD 每次启动监听的端口都不一样,因此我们需要通过一个脚本来创建 PulseAudio 的配置文件,以便 PulseAudio 能找到正确的 ESD 端口来进行输出:

#!/usr/bin/env bash

# Set up the pulseaudio remote sound
cat > ~/.pulse/default.pa <<EOF
#!/usr/bin/pulseaudio -nF

load-module module-esound-sink sink_name=esdoutput server=$ESPEAKER rate=44100
set-default-sink esdoutput
load-module module-esound-protocol-unix
load-module module-native-protocol-unix
load-module module-stream-restore
load-module module-rescue-streams
.nofail
load-module module-x11-publish
EOF
pulseaudio -k
pulseaudio -nF ~/.pulse/default.pa &

将这段脚本设置为每次登录系统的时候自动运行,这段脚本会从环境变量中获得正确的 ESD 端口,创建相应的 PulseAudio 配置文件,杀死之前启动的 PulseAudio 服务器并启动新的服务器。运行了这段脚本之后,我们就获得了一个能够将声音成功重定向到 ESD 上的 PulseAudio 服务器。

接下来,我们配置 alsa 让它能将声音输出到 PulseAudio 上来。在用户主目录下创建 alsa 的配置文件 ~/.asoundrc,内容如下:

pcm.pulse {
    type pulse
}
ctl.pulse {
    type pulse
}
pcm.!default {
    type pulse
}
ctl.!default {
    type pulse
}

至此,我们成功模拟出来了一个 alsa 声音系统,可以将所有来自 alsa 的声音重定向给 PulseAudio,然后 PulseAudio 把声音发到虚拟 ESD,然后送回本地的 nxesd,再通过本地的 OSS wrapper 发给本地的声音服务器然后我们就听到声音了。终于,网页中的 Flash 可以正常发声了。

5 NX 使用小技巧

6 无缝模式

NX 还有一种工作模式叫做无缝模式,在这个模式下,NX 不会为远程会话创建一个独立的桌面,而是在本地为每一个远程窗口创建浮动的窗口,这样操作远程窗口的时候会更加方便和自然。

要创建无缝模式的会话,只要在新建 NX 会话的时候,在 General 页里的 Desktop 选项中选择“Unix”和“Custom”,然后点击“Settings”,在“Application”底下选择无缝模式会话的主程序,在“Options”里选“Floating window”,即可创建无缝模式的会话。NX 默认在无缝模式下会在每个窗口顶端生成一个三按钮的小工具栏,用来断开或杀死当前会话,如果觉得这个小工具栏很丑陋的话,可以把它禁用掉:编辑 /usr/NX/etc/node.cfg,找到:

# EnablePulldownMenu = "1"

把前面的注释符号“#”去掉,并把之后的“1”改成“0”就可以了:

EnablePulldownMenu = "0"

以后想断开或杀死当前会话的时候,可以通过快捷键 Ctrl-Alt-T 来进行。

使用无缝模式的时候需要注意几点:

首先,只要作为无缝模式的主程序退出了,整个会话就会被杀死,因此一定记得要时刻保持主程序窗口开启。

其次,如果你喜欢 KDE,希望使用 konsole 作为无缝模式的主程序,请记得在运行 konsole 的时候加上 --nofork 参数,否则 konsole 在运行的时候会先 fork 一个子进程,在子进程里创建主窗口,父进程立刻退出,而根据无缝模式的特点,父进程退出后,NX 就会杀死整个会话,这样就没法用了。

最后,由于无缝模式仅仅只启动你指定的程序,而不会运行整个完整的桌面环境,因此 Xclient 启动过程中的所有脚本都不会自动得到执行。如果你想在 NX 会话中使用输入法,你需要在启动你的主程序之前手工运行一下加载输入法的脚本。在 Debian/Ubuntu 下,加载输入法的脚本是 /etc/X11/Xsession.d/80im-switch