2 # SPDX-License-Identifier: MIT-0
4 # Implement the systemd notify protocol without external dependencies.
5 # Supports both readiness notification on startup and on reloading,
6 # according to the protocol defined at:
7 # https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
8 # This protocol is guaranteed to be stable as per:
9 # https://systemd.io/PORTABILITY_AND_STABILITY/
23 raise ValueError("notify() requires a message")
25 socket_path
= os
.environ
.get("NOTIFY_SOCKET")
29 if socket_path
[0] not in ("/", "@"):
30 raise OSError(errno
.EAFNOSUPPORT
, "Unsupported socket type")
32 # Handle abstract socket.
33 if socket_path
[0] == "@":
34 socket_path
= "\0" + socket_path
[1:]
36 with socket
.socket(socket
.AF_UNIX
, socket
.SOCK_DGRAM | socket
.SOCK_CLOEXEC
) as sock
:
37 sock
.connect(socket_path
)
43 def notify_reloading():
44 microsecs
= time
.clock_gettime_ns(time
.CLOCK_MONOTONIC
) // 1000
45 notify(f
"RELOADING=1\nMONOTONIC_USEC={microsecs}".encode())
47 def notify_stopping():
50 def reload(signum
, frame
):
54 def terminate(signum
, frame
):
59 print("Doing initial setup")
60 global reloading
, terminating
62 # Set up signal handlers.
63 print("Setting up signal handlers")
64 signal
.signal(signal
.SIGHUP
, reload)
65 signal
.signal(signal
.SIGINT
, terminate
)
66 signal
.signal(signal
.SIGTERM
, terminate
)
68 # Do any other setup work here.
70 # Once all setup is done, signal readiness.
71 print("Done setting up")
74 print("Starting loop")
75 while not terminating
:
80 # Support notifying the manager when reloading configuration.
81 # This allows accurate state tracking as well as automatically
82 # enabling 'systemctl reload' without needing to manually
83 # specify an ExecReload= line in the unit file.
87 # Do some reconfiguration work here.
89 print("Done reloading")
92 # Do the real work here ...
94 print("Sleeping for five seconds")
100 if __name__
== "__main__":
101 sys
.stdout
.reconfigure(line_buffering
=True)
102 print("Starting app")