Linux:当会话通过 ssh+screen 启动时,wmctrl 无法打开显示

Linux:当会话通过 ssh+screen 启动时,wmctrl 无法打开显示

我在 Ubuntu 机器上使用 wmctrl 来管理在 (gnu) 屏幕内运行的脚本的窗口。

如果我从本地计算机启动屏幕会话,wmctrl 可以正常工作,包括我完全关闭终端窗口并在通过 ssh 远程连接到屏幕时发出 wmctrl 命令。相反,如果我使用 ssh 远程连接并启动屏幕,即使我从 Ubuntu 终端本地连接该屏幕会话,wmctrl 也无法工作(返回“无法打开显示”)。

我猜测有一些隐藏的屏幕参数没有以允许在远程启动时访问显示的方式进行设置——有什么想法吗?如何在远程 ssh-screen 会话中修改它,以便脚本可以访问窗口?

答案1

显示和权限

X 程序需要两条信息才能连接到 X 显示器。(请注意wmctrl,即使它访问其他进程的窗口而不是创建自己的窗口,它也是一个 X 程序。)

  • 它需要显示器的地址,通常是:0当您本地登录时,或:10:11您远程登录时,等等(但该数字可能会根据活动的 X 连接数而变化)。显示器的地址通常在环境变量中指示DISPLAY

  • 它需要显示器的密码。X 显示器密码称为魔法饼干:42。Magic cookies 不是直接指定的:它们总是存储在 X 授权文件中,这些文件是“display has cookie ”形式的记录集合123456。X 授权文件通常在环境变量中指示XAUTHORITY。如果$XAUTHORITY未设置,程序将使用~/.Xauthority

在屏幕会话中,环境变量在会话启动时确定,除非您在某个时刻明确更改它们。因此,如果您在台式机上本地启动屏幕会话,然后远程连接到该会话,$DISPLAY并且$XAUTHORITY仍然指向您的台式机。但是,如果您从某台机器 C 到台式机的 ssh 连接启动屏幕会话,则不会设置变量。(如果您在 C 上有 X 服务器并且已启用通过 ssh 会话进行 X 转发,则它们将被设置为指向 C。)

获取变量的值

据我了解,您正在尝试对桌面上显示的窗口进行操作。如果您是唯一使用台式机的人,则显示名称很可能是:0。查找 X 权限文件的位置比较困难(在 Ubuntu 的默认设置下,它位于一个具有随机生成名称的文件中)。

以下是获取DISPLAY和值的几种方法XAUTHORITY

  • 简单的解决方案是始终从您的桌面启动屏幕会话,也许在您的登录脚本中自动启动(从~/.profile;但仅当在 X 下登录时才执行此操作:测试是否DISPLAY设置为以 开头的值:(应该涵盖您可能遇到的所有情况))。在~/.profile

    case $DISPLAY in
      :*) screen -S local -d -m;;
    esac
    

    在 ssh 会话中:

    screen -d -r local
    
  • DISPLAY您还可以将和的值保存XAUTHORITY在文件中并调用这些值。在~/.profile

    case $DISPLAY in
      :*) export | grep -E ' (DISPLAY|XAUTHORITY)=' >~/.local-display-coordinates.sh;;
    esac
    

    在 ssh 会话中:

    . ~/.local-display-coordinates.sh
    screen
    
  • DISPLAY您可以从正在运行的进程中检测和的值XAUTHORITY。这很难实现自动化。您必须找出连接到要处理的显示器的进程的 PID,然后从/proc/$pid/environ( eval export $(</proc/$pid/environ tr \\0 \\n | grep -E '^(DISPLAY|XAUTHORITY)=')¹) 获取环境变量。

复制 Cookie

另一种方法(遵循Arrowmaster 的建议就是不要尝试在 ssh 会话中获取 的值$XAUTHORITY,而是让 X 会话将其 cookie 复制到 中~/.Xauthority。由于每次登录时都会生成 cookie,因此将过期值保留在 中不会有问题~/.Xauthority

如果您的主目录可通过 NFS 或其他允许远程管理员查看其内容的网络文件系统访问,则可能会出现安全问题。他们仍然需要以某种方式连接到您的机器,除非您启用了 X TCP 连接(Debian 默认关闭它们)。因此对于大多数人来说,这要么不适用(没有 NFS),要么不是问题(没有 X TCP 连接)。

要在登录桌面 X 会话时复制 cookie,请将以下几行添加到~/.xprofile~/.profile(或登录时读取的其他脚本):

case :$DISPLAY:$XAUTHORITY in
  :*:?*) XAUTHORITY=~/.Xauthority xauth merge "$XAUTHORITY";;
esac

然后在屏幕内部你只需要setenv DISPLAY :0(或显示号码是什么,但它可能如上所述:0)。

¹ 原则上,这缺少适当的引用,但在这个特定实例中$DISPLAY$XAUTHORITY不会包含任何 shell 元字符。

答案2

如果你只想运行 1 个命令,那么你很可能可以这样做:

env DISPLAY=:0 XAUTHORITY=/home/UserOfDesktop/.Xauthority wmctrl -r "Firefox" -e 0,0,0,1920,1080

确保将 DISPLAY=:0 更改为您想要操作的桌面,并将 UserOfDesktop 更改为运行 X 会话的用户的名称。

相关内容