如何配置 D-Bus 和 SSH X-Forwarding 以防止 SSH 在退出时挂起?

如何配置 D-Bus 和 SSH X-Forwarding 以防止 SSH 在退出时挂起?

我正在尝试通过 X11 转发和 SSH 运行各种 Gnome 应用程序。某些应用程序会导致首先生成“dbus-launch”应用程序。问题是,当 X 应用程序退出时,dbus-launch 不会关闭,因此必须先将其终止,然后才能正确关闭 SSH 会话。

我猜想问题在于 X/Gnome 应用程序无法与主消息总线守护进程连接,因此必须启动自己的副本?我该如何修复这个问题?或者我遗漏了什么?

这是一个例子。我启用了 X11 转发,一切似乎都运行正常。

[me@host ~]$ gnome-calculator &
[1] 4803

(此处 gcalctool 程序启动并显示到我的删除 X 服务器(Xming))

[me@host ~]$ ps
  PID TTY          TIME CMD
 4706 pts/0    00:00:00 bash
 4803 pts/0    00:00:00 gnome-calculator
 4807 pts/0    00:00:00 dbus-launch
 4870 pts/0    00:00:00 ps

(现在,关闭远程会话中的 gcalctool 应用程序后)

[me@host ~]$ ps
  PID TTY          TIME CMD
 4706 pts/0    00:00:00 bash
 4807 pts/0    00:00:00 dbus-launch
 4898 pts/0    00:00:00 ps

请注意,dbus-launch 仍处于活动状态。最糟糕的是,这会阻止 SSH 连接正常关闭,直到它被终止。

请注意,系统范围的消息守护进程正在运行,如下所示:

[me@host ~]$ ps ax
 4696 ?     Ssl   0:00 dbus-daemon --system

我在这里遗漏了什么?我以前从未见过这种行为。大概,我只见过可以不受阻碍地连接到消息总线守护进程的应用程序?我在 /etc/dbus-1 中查找了答案,但不知道该寻找什么。

先谢谢您的帮助。

[编辑]

好的,我意识到我遇到了一个常见问题。这似乎是一种相当常见的行为,但没有好的解决方案。我遇到了 SSH 挂起,因为 dbus-launch 在 tty 中仍然处于活动状态。但似乎没有好的方法让 dbus-launch 安静地发生。

查看 /etc/X11/xinit/xinitrc.d/00-start-message-bus.sh 可以得到一些线索,了解“正常”X 会话中应该发生什么。当然,当只是调用远程 X 服务器的 X 应用程序时,这不起作用。

作为临时的解决方法,我将其添加到我的 .bash_logout 中:

# ~/.bash_logout
pkill -u $USER -t `tty | cut -d '/' -f 3,4` dbus-launch

这将允许 SSH 会话关闭,但感觉很笨拙。有没有更好的解决方案?在不让 dbus 干扰的情况下运行远程 X11 应用程序的正确方法是什么?

答案1

根据 dbus-launch(1):

如果尝试使用 D-Bus 的进程未设置 DBUS_SESSION_BUS_ADDRESS,则默认情况下,该进程将尝试使用 --autolaunch 选项调用 dbus-launch 来启动新的会话总线或在 X 显示器上或 ~/.dbus/session-bus/ 中的文件中查找现有总线地址

每当自动启动时,必须启动新总线的应用程序将处于自己的小世界中;如果它尝试使用大量总线服务,它最终可能会启动一个全新的会话。这可能是次优的,甚至完全失败,具体取决于应用程序及其尝试执行的操作。

自动启动有两个常见原因。一个是 ssh 到远程机器。

因此,诀窍似乎是先启动 dbus-daemon,以便程序可以找到它。我使用:

[me@host ~]$ dbus-launch --exit-with-session gnome-terminal

除了 gnome-terminal 之外,它还启动 dbus-daemon 并设置 $DBUS_SESSION_BUS_ADDRESS在 gnome 终端中

任何从 gnome-terminal 运行的 X 程序都会运行良好,并且当 gnome-terminal 退出时,dbus-launch 会自行清理。

答案2

我想知道问题是否不是由于未知或不存在的 dbus 会话而引起的。

确实,当 SSH 会话打开时,它不会启动 dbus 会话。某些程序可能会启动它,但会话不知道它的存在(因此无法关闭它)。

不知道 dbus 会话也意味着使用 dbus 但不自行启动的程序会出现问题。

dbus 部分是针对每台机器和每个 X11 显示器的。它们的信息存储在 $HOME/.dbus/session-bus/- 但是,那里引用的进程可能已关闭,因此需要进行额外检查以确定是否需要启动 dbus。然后,将那里的变量导出到会话。

然后它就会像魔法一样起作用:)

我将以下内容放入我的 .bash_profile 文件中:

# set dbus for remote SSH connections
if [ -n "$SSH_CLIENT" -a -n "$DISPLAY" ]; then
    machine_id=$(LANGUAGE=C hostnamectl|grep 'Machine ID:'| sed 's/^.*: //')
    x_display=$(echo $DISPLAY|sed 's/^.*:\([0-9]\+\)\(\.[0-9]\+\)*$/\1/')
    dbus_session_file="$HOME/.dbus/session-bus/${machine_id}-${x_display}"
    if [ -r "$dbus_session_file" ]; then
            export $(grep '^DBUS.*=' "$dbus_session_file")
            # check if PID still running, if not launch dbus
            ps $DBUS_SESSION_BUS_PID | tail -1 | grep dbus-daemon >& /dev/null
            [ "$?" != "0" ] && export $(dbus-launch) >& /dev/null
    else
            export $(dbus-launch) >& /dev/null
    fi
fi

注意:hostnamectl 是 systemd 的一部分,可以检索 machine-id。dbus-launch 显示我们想要的变量;通过使用,export $(dbus-launch)我们可以检索 dbus-launch 的输出并导出变量

如果你希望在非交互式会话中完成它(例如从 ssh 运行命令时)请尝试将其放入 .bashrc 中(但请注意,bashrc 在每个打开的 shell 中都会执行)

答案3

当我尝试运行远程 X 命令并在 X 工具退出后使会话退出时,我遇到了同样的问题。

所以我想跑

ssh -X user@remotehost "firefox -no-remote"

但必须使用:

ssh -X user@remotehost 'export \`dbus-launch\`; dbus-launch firefox -no-remote; kill -TERM $DBUS_SESSION_BUS_PID'

关闭 Firefox 后,这也会关闭 ssh 会话。

更新

这似乎会导致服务器上运行大量 dbus-daemon 进程,因此这不是最佳选择,在两个帐户上添加 --exit-with-session 也无济于事,因为这会恢复原始行为

更新 2kill -TERM $DBUS_SESSION_BUS_PID:当我使用单引号(如@lobo所建议的)并添加以终止剩余的dbus-daemon进程时,这确实有效,如所建议的霍尔格·朱克https://blog.dhampir.no/content/how-to-prevent-ssh-x-from-hanging-on-exit-when-dbus-is-used

答案4

我将以下内容放在 $HOME/.ssh/environment 中

DBUS_SESSION_BUS_ADDRESS=

并摆脱了超时。

相关内容