如何在X会话之外(例如从控制台或SSH)运行X程序

37

如果我不是控制台上登录的用户,如何运行一个X应用程序并在该X会话上显示?假设我是root用户或者是之前登录的同一个用户,理论上我有权限这样做。但是我如何让X相信这一点呢?

下面是一些类似这种情况的例子:

  • 通过SSH登录并运行一个显示在远程计算机屏幕上的程序(不是通过SSH隧道传输的-那是完全不同的)
  • 使用ImageMagick的import命令进行定时任务截取X会话的屏幕截图
  • 为审计目的运行一个按键记录器

这是从无窗口Linux终端启动OpenGL应用程序的简化版本

2个回答

44
短答案是您必须设置 DISPLAY 环境变量,然后应用程序就可以运行。
长答案是我们有 Xauth,除非您在同一台机器上使用相同的用户运行,否则可能无法工作,除非您将 X 服务器帐户中运行的 Xauth 凭据导出到运行 X 客户端的帐户中。ssh -X 为您处理此操作,这就是它很棒的原因,但手动过程涉及在 X 服务器帐户上运行 xauth extract - $DISPLAY 并将该数据提供给客户端帐户上的 xauth merge -。(警告:数据是二进制的。)
在现代 Linux 系统上,:0 上有一个 X 会话且 X11 权威数据文件始终为 $HOME/.Xauthority,因此您通常可以在 Bash 中设置两个环境变量:
export XAUTHORITY=/home/$your_username/.Xauthority
export DISPLAY=':0'

我问这个问题是为了自己回答并记录在易于查找的地方。由于我处于GMT+7时区,我没有预料到会得到如此快的回复!告诉你吧:你介意把我的命令行示例粘贴进来吗?那样你的回答就会变成最完整的答案,然后我会接受你的回答。 - JasonSmith
霍布斯,你在吗?如果你能让它更适用于在本地机器上运行,我很乐意接受你的答案。谢谢! - JasonSmith
哇哈哈,我有足够的声望来编辑你的答案! :) 我只会添加一些命令行示例并接受你。 - JasonSmith
您可能还需要定义XAUTHLOCALHOSTNAME变量:export XAUTHLOCALHOSTNAME=localhost - palswim
4
我是疯了吗,还是那个回答并没有真正回答问题?在两个回答中,您只澄清了在SSH到机器上的X-Session中运行程序的先决条件。我错过了如何在远程机器上启动X中的程序(例如:LibreOffice)的实际答案。如果有人能进一步澄清这一点,我会非常高兴。谢谢,问候。 - atripes
1
抱歉,但是经过多次的实践后,我必须告诉你,它非常不完整。许多程序需要设置其他会话环境变量。例如,常见的KDE程序将具有错误的主题/颜色方案,一些程序在没有其dbus会话的情况下根本无法运行。 我找到的唯一两个解决方案是:1. 如果程序具有dbus接口,则sudo -u“$user”-n qdbus…是更好的选择。2. 如果没有,则必须以某种方式获取目标会话中的所有环境变量(set),并在sudo内部导出它们,然后再运行命令。 - anon

17

结论是您需要知道X显示(位于DISPLAY环境变量中)和魔法Cookie(位于一个文件中,文件名在XAUTHORITY环境变量中)。

快速且简单的方法

在运行X的系统上,如果您是root用户或与登录到X的相同用户,则假设使用最常见的显示和cookie文件(适用于任何发行版的标准桌面安装)。

env DISPLAY=:0 XAUTHORITY=/home/whoever/.Xauthority /path/to/my/X/program

更加可靠的方法

从已经运行的X程序的环境中找到它们。如果您是root用户或使用同一用户登录,这将告诉您(如果用户正在使用GNOME):

cat /proc/`pgrep -f ^x-session-manager`/environ \
  | ruby -ne 'puts $_.split("\0").select { |e| e =~ /^(DISPLAY|XAUTHORITY)=/ }'

嘿,有没有办法在Java程序内部更改显示环境变量,以便Java程序执行的操作与相应的环境相对应? - raju

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接