![如何配置 D-Bus 和 SSH X-Forwarding 以防止 SSH 在退出时挂起?](https://linux22.com/image/589472/%E5%A6%82%E4%BD%95%E9%85%8D%E7%BD%AE%20D-Bus%20%E5%92%8C%20SSH%20X-Forwarding%20%E4%BB%A5%E9%98%B2%E6%AD%A2%20SSH%20%E5%9C%A8%E9%80%80%E5%87%BA%E6%97%B6%E6%8C%82%E8%B5%B7%EF%BC%9F.png)
我正在尝试通过 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=
并摆脱了超时。