如何通过SSH在远程Linux PC上启动GUI软件

有时候我需要在我的远程PC上启动XMBC媒体播放器或其他GUI软件(作为媒体中心的小型Xubuntu PC)。
通常,我通过在远程PC上启动X11vnc服务器,然后使用Xvnc客户端连接到Xfce桌面来实现这一点。
有没有办法通过SSH在远程Linux PC上启动GUI软件呢?
谢谢!

可以确认,如果远程客户端也是Mac,选择答案中的方法有效。在macOS Sierra上成功运作。 - Benjamin R
5个回答

是的。您只需要在ssh会话中运行export DISPLAY=:0(或者远程显示器的编号)即可,程序将在远程显示器上运行。以下是一个快速示例:
oli@bert:~$ ssh tim
oli@tim:~$ export DISPLAY=:0
oli@tim:~$ firefox

Firefox现在正在运行在tim的显示器上。
然而,当你关闭ssh会话时,大部分情况下远程应用程序也会关闭。如果你想要断开ssh连接但保持应用程序运行,你需要以特殊的方式启动它,比如使用screen(将ssh会话保持在后台运行)或者nohup,或者其他方法。关于这个问题,最近还有另一个相关的问题,可以参考这里获取更多信息。
你可以将所有操作缩减为一个命令,该命令将连接、内联导出显示器,并以一种不会在ssh会话结束后关闭应用程序的方式启动应用程序。
ssh tim "DISPLAY=:0 nohup firefox"

当我尝试使用它时(顺便说一句,我是从Abiword上尝试的),它显示“没有显示:这可能不是你想要的。” - PyRulez
2注意第一行中的“或者无论远程显示器被编号为什么”。如果它不是第一个图形服务器,它可能是:1或更高。运行w命令查看谁登录了以及他们在哪里。这将告诉您DISPLAY号码。 - Oli
我确实有一个显示器0,它是唯一的显示器,而且它在物理上是开启并正常工作的。 - PyRulez
3怎样把它关掉? - akxer
@akabhirav 你是什么意思? - Oli
我已经启动它了,我所做的每件事都在我的电脑屏幕上打开。我希望它恢复正常,并停止这样做,而不是打开一个新的窗口。 - akxer
3unset DISPLAY - Oli
8有时候你想要做相反的事情,即在本地运行X应用程序,只需使用-Y进行连接,然后运行你的应用程序ssh -Y <remoteip> - Postadelmaga
我只有鼠标,从命令行远程启动键盘真的非常有帮助!:) ssh user@localhost "DISPLAY=:0 nohup onboard" - GTodorov
你想要启动整个 Unity GUI 会话吗? - Lucas Pottersky
我尝试从我的Linux机器通过SSH登录到Mac电脑(Sierra版本),结果完全符合预期。我可以在我的Mac电脑上使用mpv播放视频文件,并且它还能传递键盘快捷键,前提是终端会话是活动窗口。这真是太厉害了,非常感谢! - Benjamin R
当我尝试使用这个时,我只会得到“未指定协议 无法初始化服务器:无法连接:拒绝连接 错误:无法打开显示器::0”的信息。 - Luca Cappelletti
请注意,$DISPLAY 的值应为 :0: 不是导出语法的一部分。 - Tejas Kale

取决于您想在哪里看到应用程序显示

在本地计算机上显示应用程序

您首先使用附加的-Y选项ssh到远程计算机,然后运行应用程序(例如firefox):

ssh -Y ...
firefox

如果-Y不起作用,请检查远程PC上的sshd配置(参见Denis Lukinykh的答案)。另一个类似的选项是-X。请谷歌了解它们之间的区别。
要在远程PC上显示应用程序的现有会话,您需要使用用户A登录远程PC并保持会话打开。然后,您可以使用相同的用户A通过ssh启动应用程序(例如firefox),方法如下:
ssh A@...
DISPLAY=:0 nohup firefox

在任何地方显示应用程序

您需要安装并启动 xvfb。xvfb 将在 DISPLAY 10 创建一个不可见的 X 会话。然后,您可以启动您的应用程序,并将其输出定向到该 DISPLAY

sudo apt install xvfb
sudo Xvfb :10 -ac -screen 0 1024x768x24 &
DISPLAY=:10 firefox

3你还可以使用xvfb-run,它包装了Xvfb,并且非常适合如果你只想运行一个命令的话。 - alexpotato
非常感谢!“将应用程序隐藏起来”是我唯一有效的方法。 - mbnoimi

一种现代化的解决方案,适用于Wayland会话,设置所有现代会话中使用的环境变量(XDG_RUNTIME_DIR、GTK_MODULES、XDG_DATA_DIRS、XAUTHORITY、SESSION_MANAGER等),将应用程序的控制台输出转发到日志,并在后台运行,而不会占用您的ssh shell或在关闭ssh会话时退出。
ssh tim 
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$UID/bus
systemd-run --user firefox

1在我的情况下,DBUS_SESSION_BUS_ADDRESS 环境变量已经是正确的,所以这就更容易了。 - Will S
是否有可能为其分配一个ID,以便稍后可以要求systemd停止它? - Andreas
@Andreas,“systemd-run”命令输出“Running as unit: run-u544.service”(544为ID),你可以使用“systemctl --user stop run-u544.service”来终止该服务。 - undefined
1@EricReed 在发现了--unit=选项之后,这个功能变得非常有用,正是我所需要的:现在我可以在静态环境中启动和停止应用程序,而在这些环境中我无法动态地持久化任何数据,比如在iOS的快捷方式中,只需使用systemctl --user start kodi || systemd-run --user --unit=kodi kodisystemctl --user stop kodi即可。 - undefined

在远程主机上进行以下设置:
ssh remotehost 'grep -i x11 /etc/ssh/sshd_config'
   X11Forwarding yes
   X11DisplayOffset 10 

之后,您可以运行图形用户界面应用程序:
ssh -Y -t remotehost 'sudo gparted'

或者

ssh -Y remotehost
sudo gparted

假设你想要运行 gnome-disks

你需要两个 SSH 会话。一个用于运行软件(在这种情况下是 gnome-disks)。第二个会话用于执行你想要做的任何操作。

在第一个会话中执行以下命令:

    export DISPLAY=:0
    gnome-disks