我正在学习如何使用 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 10
s,以便您在观察输出时可以看到发生了什么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
。我不知道如何解决这个问题。