Dunst: 弄清楚如何将运行的 dunst 作为 systemd 服务处理

创建于 2017-04-03  ·  37评论  ·  资料来源: dunst-project/dunst

@nmschulte评论中提到,如果未安装服务文件,则 dbus 服务文件无法启动 dunst。

仅当 dbus 以--systemd-activation标志启动时才会发生这种情况,并且在这种情况下,如果找不到服务文件,它会忽略Exec行。 我们应该要么

  • 从 dbus 服务文件中删除SystemdService行,本质上不允许默认情况下由 systemd 管理 dunst 或
  • 考虑官方支持systemd安装,默认安装unit文件。

作为在这个问题范围内的附加说明, @mathstuf同一个线程中链接了一个问题,显然 systemd dbus 单元在系统总线而不是会话总线中看起来应该是它们应该的。
我们应该

  • 验证报告的有效性
  • 决定我们是否要将 systemd 单元类型更改为 simple 而不是 dbus

最有用的评论

你是对的@smcv ,感谢您追踪@WhyNotHugo @magandrez。 我现在用 43c6145 删除了WantedBy

所有37条评论

一个短期的解决方案可能是:注释掉服务文件中的SystemdService行,可能在其上方加上相关注释,并在构建过程中添加注释( make install目标,或install-service目标)关于可选(非install ed) dunst.systemd.service文件(注意它需要重命名以匹配 D-Bus 服务中的假设文件)。

请注意,我只是将此文件安装到我的PREFIX~/.local/share/systemd/user/dunst.service )中,并且拥有两个具有相同名称的D-Bus服务文件(文件名和内部服务名)并不复杂)。 我还在~/.config/systemd/user.conf ( DefaultEnvironment="PATH=/home/nmshculte/.local/bin:$PATH" ) 中将更改保留为DefaultEnvironment ,但我认为在这种情况下没有必要这样做。

设置PATH不是必需的,因为 systemd 需要Exec*行中可执行文件的完整路径。

虽然它有点笨拙(阅读:配置影响 systemd 的所有用户单元,而不仅仅是 D-Bus/Dunst 的环境),但对于那些使用 Dunst 运行脚本的人来说,这是一个重要的细节(Dunst 支持运行由通知属性匹配的脚本)并期望他们的PATH来自例如~/.profile (这被称为...登录(或交互式?)会话?我不确定正确的术语。)。

也可以在每个脚本中处理PATH问题,但是没有说 Dunst 配置(因此关心PATH的脚本)不能用于多个 Dunst 实例(尽管...也许这不可能发生;我以为我在测试中看到了一个用例,但我可能只是误解了)。

啊。 我发现最好有一个像environment.target这样的目标,其中我有foo-env.service文件,这些文件在启动服务时处理systemctl --user set-environment调用,在停止服务时处理unset-environment . 这些服务是Before=BindsTo= environment.target 。 对于 X11 特定的设置,还有一个x11-environment.target 。 然后我的dunst.serviceRequires=After= x11-environment.target以确保它具有正确的环境。

这有点复杂,但它可以工作,甚至可以让事情从下到上了解我的ssh-agent之类的东西,而不是尝试在每个.service文件中设置SSH_AGENT_SOCK ,这可能关心它。

(我的整个设置由systemd管理,包括启动 X、窗口管理器等,所以我没有.profile或(有意义的) .xinitrc 。)

仅当 [dbus-daemon] 以--systemd-activation标志启动时才会发生这种情况,并且在这种情况下,如果找不到服务文件,它会忽略Exec行。

(我是上游 D-Bus 维护者。)

是的,它就是这样工作的。 在dbus-daemon --session--systemd-activation启动的系统上,每个 D-Bus 会话服务要么是传统的 D-Bus 服务(总是通过Exec运行,就好像--systemd-activation没有被使用,没有SystemdService )或混合 D-Bus/systemd 服务(总是通过启动SystemdService来运行,而不是Exec )。

您必须安装将 dunst 作为 systemd 用户服务运行所需的一切(单元文件和SystemdService行),或者什么都不安装。 提供SystemdService行但不提供它引用的单元文件是不正确的,就像使用Exec=/usr/local/bin/dunst-wrapper-script将 D-Bus 服务安装到/usr/local/share/dbus-1/services是无效的一样Exec=/usr/local/bin/dunst-wrapper-script无需安装dunst-wrapper-script

一个短期的解决方案可能是:注释掉服务文件中的SystemdService行,可能在其上方加上相关注释,并在构建过程中添加注释( make install目标,或install-service目标)关于可选(未安装) dunst.systemd.service文件(注意它需要重命名以匹配 D-Bus 服务文件中的假设)。

这将比目前的情况更好。

更好的是,IMO 将安装 systemd 服务。 在非 systemd 系统上,以及 OS 集成商未选择从 systemd 启动dbus-daemon --session --systemd-activation的 systemd 系统上,它是无用但无害的(一个额外的安装文件,不会读取任何内容)。 在启用了 dbus-daemon 的 systemd 激活功能的系统上,它会导致 dunst 被放置在自己的 cgroup 中以进行管理和资源控制,而不是被视为 dbus-daemon 的一部分。

(如果像 Debian 或 Fedora 这样的发行版设置了你的 dbus-daemon 和 systemd,它们就是你的操作系统集成商。如果你自己做,你就是操作系统集成商。无论哪种方式,都需要由知道他们做什么的人来完成。重新做。)

虽然它有点笨拙(阅读:配置影响 systemd 的所有用户单元,而不仅仅是 D-Bus/Dunst 的环境),[操纵激活环境是]对于使用 Dunst 运行脚本的人来说是一个重要的细节

是的,为 systemd 激活的事物提供正确的环境很重要,但这不是 Dunst 的工作。 安排将正确的环境变量推送到systemd --userdbus-daemon --session中,包括如果认为有必要从~/.profile上传它们,是操作系统集成商的工作:这是所有用户服务都需要做的事情。

老实说,我看不出这里还有更多可以做的事情。 提供的dunst.service文件在正确配置的系统上工作正常(尽管仅适用于 X11! )。

这里唯一需要做的是删除Environment=DISPLAY=:0行,因为:

  1. 这应该由其他地方的systemctl --user set-environment设置。
  2. 这个假设不是普遍有效的。
  3. 这打破了 Wayland 的麻烦,需要手动启动它(例如:不是通过 systemd),或编辑文件。

除此之外,dunst 提供的代码只有在 OS Integrator 提供的内容不一致时才会失败,并且在此处/下游对此无能为力。

老实说,我看不出这里还有更多可以做的事情

请按照第一条评论所说的去做:要么从 D-Bus 服务文件中删除SystemdService行,要么在安装 D-Bus 服务文件的同时安装 systemd 单元。

(或者,如果您坚持它是可编译时可配置的,那么当且仅当您要安装 systemd 单元时才写出SystemdService行 - 但我个人认为这是不必要的复杂性,特别是在一个项目中使用 Autoconf 或类似的。无条件安装 systemd 单元不会伤害非 systemd 用户,除非存在未使用的文件,就像安装手册页不会伤害不阅读手册页的人一样。)

除此之外,dunst 提供的代码只有在 OS Integrator 提供的内容不一致时才会失败

目前 dunst 内部不一致:它总是告诉 dbus-daemon 尽可能使用 systemd 进行激活,但随后不会安装该 systemd 激活工作所需的文件。

dbus-daemon 在将激活委托给 systemd 之前不会检查引用的SystemdService是否存在 - 它不能,因为它不知道 systemd 将搜索哪些目录。

因此,简而言之,关闭它需要做的事情是:

  • #324
  • 始终将 dunst.service 文件安装到/usr/lib/systemd/user/dunst.service (通过make install )。

始终将 dunst.service 文件安装到 /usr/lib/systemd/user/dunst.service(通过 make install)

这也应该考虑PREFIX吗?

是的,你是对的,它应该。

这也应该考虑 PREFIX 吗?

是的,但使用${prefix}/lib ,而不是${libdir} 。 systemd 总是在lib中查找单元,即使在共享库等会进入并行目录(如lib64lib/x86_64-linux-gnu的系统上)。

我对默认情况下将 dunst 设置为 systemd 服务的担忧之一是,根据我的测试,如果 dunst 由于任何原因崩溃,dbus 会在下一个通知通过时愉快地重新启动它,而如果 dunst 是它会导致挂起和超时配置为 systemd 服务并且它处于失败状态。

一个解决方案可能是设置Restart=on-failure但我不确定这会有多有效,因为它取决于超时,我似乎无法找到一种方法来设置它,以便它只从 dbus 重新启动激活。

设置超时是一个有效的选项,但如果它由于一个原因在另一个原因上持续崩溃(即 X 服务器尚未启动)可能会导致相当多的日志垃圾邮件。

我对默认情况下将 dunst 设置为 systemd 服务的担忧之一是,根据我的测试,如果 dunst 由于任何原因崩溃,dbus 会在下一个通知通过时愉快地重新启动它,而如果 dunst 是它会导致挂起和超时配置为 systemd 服务并且它处于失败状态。

我刚刚测试过,但似乎并非如此:

  • Dunst 作为 systemd 服务运行。
  • pkill -KILL dunst
  • systemd 现在将其报告为失败。
  • notify-send asdf
  • 显示通知。 systemd 再次将该服务报告为活动状态。

设置超时是一个有效的选项,但如果它由于一个原因在另一个原因上持续崩溃(即 X 服务器尚未启动)可能会导致相当多的日志垃圾邮件。

这里提到的graphical.session.target不包括吗?

我刚测试过,好像不是这样

你是对的,我认为 systemd 是原因,但显然不是。 经过更多测试后,似乎我提到的事情发生了,因为我将 dunst 设置为在启动时失败以进行测试(通过禁用显示服务器)并且 dbus 不承认激活失败并导致该地址的所有消息挂起,直到它超时。

这里提到的 graphics.session.target 不包括吗?

根据手册页

只要任何图形会话正在运行,此目标就会处于活动状态。 它用于在会话终止时停止仅适用于图形(X、Wayland 等)会话的用户服务。

所以它只是为了停止它,它不会对它设置依赖。 我不确定在显示服务器上设置硬依赖的正确方法是什么。

所以它只是为了停止它,它不会对它设置依赖。 我不确定在显示服务器上设置硬依赖的正确方法是什么。

man systemd.unit

绑定到=
配置需求依赖,风格与 Requires= 非常相似。 但是,这种依赖类型更强:除了 Requires= 的效果外,它声明如果绑定到的单元停止,则该单元也将停止。 这意味着绑定到另一个单元的单元突然进入非活动状态也将被停止。 单元可能由于不同的原因突然、意外地进入非活动状态:服务单元的主进程可能会自行终止,设备单元的后备设备可能已拔出,或者挂载单元的挂载点可能会在没有参与的情况下被卸载系统和服务管理器。

当在同一单元上与 After= 结合使用时,BindsTo= 的行为会更加强大。 在这种情况下,严格绑定到的单元必须处于活动状态才能使该单元也处于活动状态。 这不仅意味着一个单元绑定到另一个突然进入非活动状态的单元,还意味着一个绑定到另一个单元由于条件检查失败而被跳过(例如 ConditionPathExists=、ConditionPathIsSymbolicLink=、... — 见下文)将停止,如果它正在运行。 因此,在许多情况下,最好将 BindsTo= 与 After= 结合使用。

TBH,不过我不会太担心这个; 如果应用程序在显示服务器未运行时尝试发送通知,则预计会失败。

实际上,仔细想想, BindsTo并不是一个好主意:如果应用程序查询通知服务器,它将启动桌面环境。 这是不可取的。

  • 应用程序:“通知守护程序是否正在运行”。
  • Systemd:尝试启动整个图形环境(即使 Xorg 没有运行)。

呸,擦掉所有这些,我们在讨论PartOf ,而不是BindsTo ,我把我的狗屎弄混了。

我认为PartOf就足够了:当图形环境停止时停止垃圾。 在没有图形环境运行时尝试发送通知应该会失败,我认为这种情况不需要额外考虑。

在没有图形环境运行时尝试发送通知应该会失败,我认为这种情况不需要额外考虑。

你是对的,我之前所说的是错误的假设,即 systemd 没有重新启动失败的单元。

请将PartOf行添加到 #324。 合并后,我将更新 Makefile 以安装 systemd 服务文件。

通过 #324 关闭

你好,

我通过以下方式遇到了上述问题:

  • 启动系统(Debian Testing + LightDM + i3),systemd 报告 dunst 处于失败状态。 我使用 notify-send 发出通知,systemd 报告该服务已启动并正在运行。 这是期望的行为吗?

我运行最新的 dunst,其中包括在 #324 中所做的更改

谢谢

在发送任何通知之前,它是如何处于failed状态的?

当第一个通知到达时,它由 DBus 激活。

实际上,我刚刚意识到可以将服务配置为在登录时自动启动,但它也会在_之前_启动图形会话。

可能有两个解决方法:

  • 删除WantedBy ,因此运行systemd --user enable dunst拒绝链接它。 这可能是最有意义的,因为 dbus 会在需要时自动启动 dunst。
  • WantedBy更改为PartOf=graphical-session.target ,这样至少它会延迟到图形会话启动为止。 不过,很难找到这样做的理由。

嗯,我去了第一个解决方法,但根本没有工作。

失败状态仍然是 journalctl 声明

Mar 19 18:18:41 hecate systemd[861]: Starting Dunst notification daemon...
Mar 19 18:18:41 hecate dunst[880]: CRITICAL: Cannot open X11 display.
Mar 19 18:18:41 hecate systemd[861]: dunst.service: Main process exited, code=exited, status=1/FAILURE

我应该发布--full吗?

扩展上述内容:这是重新启动和登录后的失败状态。

systemctl --user status dunst的输出是什么?

启动并登录 X 会话后如下:

● dunst.service - Dunst notification daemon
     Loaded: loaded (/home/manuel/.config/systemd/user/dunst.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Thu 2020-03-19 19:55:19 EET; 1min 16s ago
       Docs: man:dunst(1)
    Process: 905 ExecStart=/usr/bin/dunst (code=exited, status=1/FAILURE)
   Main PID: 905 (code=exited, status=1/FAILURE)

Mar 19 19:55:19 hecate systemd[886]: Starting Dunst notification daemon...
Mar 19 19:55:19 hecate dunst[905]: CRITICAL: Cannot open X11 display.
Mar 19 19:55:19 hecate systemd[886]: dunst.service: Main process exited, code=exited, status=1/FAILURE
Mar 19 19:55:19 hecate systemd[886]: dunst.service: Failed with result 'exit-code'.
Mar 19 19:55:19 hecate systemd[886]: Failed to start Dunst notification daemon.

似乎以某种方式将 dunst 设置为登录时自动启动,而不是使用 dbus-activation。

systemctl --user disable dunst应该可以解决问题。

嗯,它不会以任何方式影响。 禁用 dunst 后,重新启动时系统仍处于故障状态。

发出通知时,(我假设)dbus 启动服务并且系统恢复。 我认为这是在挑剔,在这一点上。

但我仍然对原因很感兴趣。

这很奇怪。 还是提前自动启动? 现在systemctl --user status dunst的输出是什么?
find .config/systemd -iname "*dunst*"呢?

systemctl 报告 dunst 的以下状态

● dunst.service - Dunst notification daemon
     Loaded: loaded (/usr/lib/systemd/user/dunst.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Fri 2020-03-20 12:16:13 EET; 9s ago
       Docs: man:dunst(1)
    Process: 904 ExecStart=/usr/bin/dunst (code=exited, status=1/FAILURE)
   Main PID: 904 (code=exited, status=1/FAILURE)

Mar 20 12:16:13 hecate systemd[885]: Starting Dunst notification daemon...
Mar 20 12:16:13 hecate dunst[904]: CRITICAL: Cannot open X11 display.
Mar 20 12:16:13 hecate systemd[885]: dunst.service: Main process exited, code=exited, status=1/FAILURE
Mar 20 12:16:13 hecate systemd[885]: dunst.service: Failed with result 'exit-code'.
Mar 20 12:16:13 hecate systemd[885]: Failed to start Dunst notification daemon.

并且 find 在 .config/systemd 下找不到任何东西

为了完整性:

$ systemctl --user cat dunst.service 
# /usr/lib/systemd/user/dunst.service
[Unit]
Description=Dunst notification daemon
Documentation=man:dunst(1)
PartOf=graphical-session.target

[Service]
Type=dbus
BusName=org.freedesktop.Notifications
ExecStart=/usr/bin/dunst

[Install]
# WantedBy=default.target

我有点困惑为什么它仍然说禁用。 systemctl --user disable dunst确实禁用了它,对吗?

这是在什么发行版上? 是否在系统范围内强制启用? tree /etc/systemd/user/ ?

是的,它被禁用了,.config/systemd/user 下没有链接

它是 Debian 测试的一个网络。

$ tree /etc/systemd/user
/etc/systemd/user
├── default.target.wants
│   ├── dunst.service -> /usr/lib/systemd/user/dunst.service
│   └── pulseaudio.service -> /usr/lib/systemd/user/pulseaudio.service
└── sockets.target.wants
    ├── dirmngr.socket -> /usr/lib/systemd/user/dirmngr.socket
    ├── gpg-agent-browser.socket -> /usr/lib/systemd/user/gpg-agent-browser.socket
    ├── gpg-agent-extra.socket -> /usr/lib/systemd/user/gpg-agent-extra.socket
    ├── gpg-agent.socket -> /usr/lib/systemd/user/gpg-agent.socket
    ├── gpg-agent-ssh.socket -> /usr/lib/systemd/user/gpg-agent-ssh.socket
    ├── pk-debconf-helper.socket -> /usr/lib/systemd/user/pk-debconf-helper.socket
    └── pulseaudio.socket -> /usr/lib/systemd/user/pulseaudio.socket

2 directories, 9 files
/etc/systemd/user
├── default.target.wants
│   ├── dunst.service -> /usr/lib/systemd/user/dunst.service

该服务由 Debian 打包在系统范围内启用,因为在安装它时,它有WantedBy=default.target (我认为这是一个错误 - 它不应该在 GUI 之前启动,无论如何不应为其他通知实现的用户启动,例如 GNOME Shell)。 按用户禁用它不会在系统范围内禁用它。

你是对的@smcv ,感谢您追踪@WhyNotHugo @magandrez。 我现在用 43c6145 删除了WantedBy

我有个问题。 现在dunst是静态的。 但是dbus --session不能运行它,因为没有DISPLAY变量。 我如何在那里安装它? 这是分发设置问题还是您的问题( dbus不是图形应用程序,原则上应该有DISPLAY吗?)? 我的它只适用于特定的DM吗?

LightDM==1:1.30.0-4
i3-gaps==4.18.2-2
dusnt==1.5.0-1.0
dbus==1.12.20-1

ps 我知道我可以使用systemctl --user start {}

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

wpovell picture wpovell  ·  5评论

knopwob picture knopwob  ·  5评论

progandy picture progandy  ·  4评论

chronus7 picture chronus7  ·  5评论

patrick-motard picture patrick-motard  ·  6评论