如何使用 systemd 通知

如何使用 systemd 通知

我正在学习如何使用 systemd 通知。我认为它是一种机制,允许一个进程向另一个进程发送通知。

因此,我尝试使用命令发出通知systemd-notify --ready --status="hello"。然后我收到错误:No status data could be sent: $NOTIFY_SOCKET was not set。它似乎需要一个侦听器,就像套接字一样。但我不知道如何创建侦听器来接收此通知。

另外,我知道 systemd 的服务有几种不同的类型,其中一种是notify。文档说,Type=notify: identical to Type=simple, but with the stipulation that the daemon will send a signal to systemd when it is ready.。所以看起来类型为通知的服务也可以发送通知,但我也不知道如何使用它。

答案1

systemd-notify工具专门供使用作为 systemd 服务运行的 shell 使用Type=notify

如果您使用 设置服务Type=notify,systemd 将自动设置一个与 systemd 的通信套接字并将其路径导出到 下的服务$NOTIFY_SOCKET

它还将监听该套接字中的特殊消息,比如服务是否准备就绪(在这种情况下,systemd 会将其转换为状态started,因为初始化已完成)以及服务的自我报告状态,这也将在输出中报告systemctl status mytest.service(假设服务名为mytest)。

您可以阅读的手册页systemd-notify对于所有细节,即使那里有很多复杂性...也许最后的例子有助于说明它是如何工作的。


让我们用这个例子来进行实际实验!

在系统的某处创建类似下面的脚本,例如/usr/local/bin/mytest.sh

#!/bin/bash

mkfifo /tmp/waldo
sleep 10
systemd-notify --ready --status="Waiting for data…"

while : ; do
        read a < /tmp/waldo
        systemd-notify --status="Processing $a"

        # Do something with $a …
        sleep 10

        systemd-notify --status="Waiting for data…"
done

我添加了一些sleep 10s,以便您在观察输出时可以看到发生了什么systemctl status mytest.service

使脚本可执行:

$ sudo chmod +x /usr/local/bin/mytest.sh

然后创建/etc/systemd/system/mytest.service,内容如下:

[Unit]
Description=My Test

[Service]
Type=notify
ExecStart=/usr/local/bin/mytest.sh

[Install]
WantedBy=multi-user.target

然后重新加载 systemd(以便它了解该单元)并启动它:

$ sudo systemctl daemon-reload
$ sudo systemctl start mytest.service

然后时不时观察状态输出:

$ systemctl status mytest.service

您会看到它starting在前 10 秒内出现,之后它started的状态将为“正在等待数据...”。

现在将一些数据写入 FIFO(您需要使用tee以 root 身份运行它):

$ echo somedata | sudo tee /tmp/waldo

并观察状态:

$ systemctl status mytest.service

它将显示服务状态为“正在处理一些数据”10 秒,然后返回到“正在等待数据...”。

如果您使用 C 或其他支持 systemd 绑定的语言编写此代码,则可以使用该sd_notify()函数来实现此目的。如果您熟悉 C,您可能需要查看sd_通知(3)请参阅手册页。

答案2

要了解 sd_notify 的消息格式,你可以尝试这个:

1号航站楼:

$ socat unix-recv:/tmp/test.sock -

2 号航站楼:

$ NOTIFY_SOCKET=/tmp/test.sock systemd-notify --ready --status="hello"

您将在终端 1 中看到结果:

READY=1
STATUS=hello

答案3

这不是一个完整的答案,但我使用“netcat”得到了这个答案

A)在一个终端会话中,执行:

export NOTIFY_SOCKET=/tmp/test.sock
nc -l -U -u /tmp/test.sock

B)打开另一个终端会话并执行:

export NOTIFY_SOCKET=/tmp/test.sock
systemd-notify --read --status="hello"`

这有效,但netcat你会得到nc: connect: Invalid argument。我不知道如何解决这个问题。

相关内容