我大量使用 tmux,并且有一些脚本使用通知发送来向我发送屏幕通知。我发现一种特殊情况,通知发送会失败,除了启动新的 tmux 会话(这显然不是理想的做法)之外,我还没有找到其他解决方法。
如果我创建一个新的 tmux 会话并使用通知发送,我将看到通知弹出,没有任何问题。但是,一旦我脱离 tmux 会话,然后稍后重新连接到它,通知发送将失败并显示以下消息:
$ notify-send test
(notify-send:26902): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed
除了将我的工作转移到新的 tmux 会话中之外,我还没有找到其他解决方案,但这并不理想,因为这首先就否定了使用 tmux 的意义。我不确定发生了什么。也许是在终端和 tmux 之间有某种 IPC 路径被破坏了,而这些路径是通知发送使用的,或者是其他原因?我有什么办法可以恢复通知发送的功能,而不会丢失现有的 tmux 会话?
答案1
虽然错误消息不是最理想的,但它似乎可以理解为“无法连接到 D-Bus 会话总线”。
notify-send 通过 D-Bus 发送 IPC 消息 - 具体来说,通过会话总线,其地址在每次 dbus-daemon 启动时随机分配并存储在$DBUS_SESSION_BUS_ADDRESS
环境变量中。
通常它并不特定于当前终端– 它是从 X11 会话管理器继承而来的,因此如果您同时启动两个终端,它们都将使用相同的会话总线。
但是如果你从 tmux 分离,重新启动 X11 会话并重新连接,新会话将有一个新的总线,但其中正在运行的所有进程仍将具有老的环境。
部分解决方法是将此环境变量添加到 tmux 的update-environment
设置中:
set -g update-environment "DBUS_SESSION_BUS_ADDRESS DISPLAY SSH_AUTH_SOCK XAUTHORITY"
请注意,这仅适用于新的该会话中的 tmux 窗口;tmux 不可能更新现存的贝壳。
或者,让您的 X11 启动脚本将 DBUS_SESSION_BUS_ADDRESS 的值存储到某个文件中,并制作一个包装脚本,notify-send
在运行真正的/usr/bin/notify-send
.
这类似于 D-Bus“自动启动”的工作方式(或曾经的工作方式)。如果$DISPLAY
设置了但未$DBUS_SESSION_BUS_ADDRESS
设置,则会话总线客户端将查找~/.dbus/
当前显示器的总线地址。但是,“自动启动”机制由于各种原因而被弃用(它不稳定,留下垃圾,让人认为 D-Bus 需要 X11,等等)。
一些发行版正在转向“用户总线”模型,其中每个用户都有恰好一个“会话”总线位于固定位置(通常在unix:path=/run/user/$UID/bus
)。这样,环境就不会改变。(即使它完全缺失,大多数 D-Bus 客户端也已经检查了该特定位置。)
在 Debian 上,可以通过安装来选择用户总线模型dbus-user-session
- 尽管它可能会破坏其他一些东西。