Ubuntu – How to use systemd notify

notificationsystemd

I'm learning how to use systemd notify. I'm thinking it is a kind of mechanism, which allows a process to send a notification to another process.

So, I tried to make a notification with the command systemd-notify --ready --status="hello". Then I got an error: No status data could be sent: $NOTIFY_SOCKET was not set. It seems that it needs a listener, just like the socket. But I don't know how to make a listener to receive this notification.

Also, I've known that the service of systemd has some different types, one of them is notify. The doc said, Type=notify: identical to Type=simple, but with the stipulation that the daemon will send a signal to systemd when it is ready.. So it seems that the service whose type is notify can send notification too, but I don't know how to use it either.

Best Answer

The systemd-notify tool is specifically meant to be used by a shell that runs as a systemd service using Type=notify.

If you set up a service using Type=notify, systemd will automatically set up a communication socket back to systemd and will export its path to the service under $NOTIFY_SOCKET.

It will also listen for special messages in that socket, such as whether the service is ready (in which case systemd will transition it to status started, since initialization is completed) and also the self-reported status of the service, which will also be reported in the output of systemctl status mytest.service (assuming a service called mytest.)

You can read the man page of systemd-notify for all the details, even though there's a lot of complexity there... Perhaps the example at the end is useful in illustrating how it works.


Let's use that example for a hands-on experiment!

Create a script like the one below somewhere in your system, such as /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

I added some sleep 10s so you can see what's happen, when watching the systemctl status mytest.service output.

Make the script executable:

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

Then create /etc/systemd/system/mytest.service, with contents:

[Unit]
Description=My Test

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

[Install]
WantedBy=multi-user.target

Then reload systemd (so it learns about the unit) and start it:

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

Then watch status output, every so often:

$ systemctl status mytest.service

You'll see it's starting for the first 10 seconds, after which it will be started and its status will be "Waiting for data…".

Now write some data into the FIFO (you'll need to use tee to run it as root):

$ echo somedata | sudo tee /tmp/waldo

And watch the status:

$ systemctl status mytest.service

It will show the status of the service as "Processing somedata" for 10 seconds, then back to "Waiting for data…".

If you were to write this code in C or another language that supports systemd bindings, you would use the sd_notify() function for this purpose. If you're familiar with C, you might want to take a look at the sd_notify(3) man page.