mirror of
https://github.com/systemd/systemd.git
synced 2026-08-10 17:14:31 +00:00
113 lines
2.7 KiB
Python
Executable File
113 lines
2.7 KiB
Python
Executable File
#!/usr/bin/python
|
|
# SPDX-License-Identifier: MIT-0
|
|
#
|
|
# Implement the systemd notify protocol without external dependencies.
|
|
# Supports both readiness notification on startup and on reloading,
|
|
# according to the protocol defined at:
|
|
# https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
|
|
# This protocol is guaranteed to be stable as per:
|
|
# https://systemd.io/PORTABILITY_AND_STABILITY/
|
|
|
|
import errno
|
|
import os
|
|
import signal
|
|
import socket
|
|
import sys
|
|
import time
|
|
|
|
reloading = False
|
|
terminating = False
|
|
|
|
|
|
def notify(message):
|
|
if not message:
|
|
raise ValueError('notify() requires a message')
|
|
|
|
socket_path = os.environ.get('NOTIFY_SOCKET')
|
|
if not socket_path:
|
|
return
|
|
|
|
if socket_path[0] not in ('/', '@'):
|
|
raise OSError(errno.EAFNOSUPPORT, 'Unsupported socket type')
|
|
|
|
# Handle abstract socket.
|
|
if socket_path[0] == '@':
|
|
socket_path = '\0' + socket_path[1:]
|
|
|
|
with socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM | socket.SOCK_CLOEXEC) as sock:
|
|
sock.connect(socket_path)
|
|
sock.sendall(message)
|
|
|
|
|
|
def notify_ready():
|
|
notify(b'READY=1')
|
|
|
|
|
|
def notify_reloading():
|
|
microsecs = time.clock_gettime_ns(time.CLOCK_MONOTONIC) // 1000
|
|
notify(f'RELOADING=1\nMONOTONIC_USEC={microsecs}'.encode())
|
|
|
|
|
|
def notify_stopping():
|
|
notify(b'STOPPING=1')
|
|
|
|
|
|
def reload(signum, frame):
|
|
global reloading
|
|
reloading = True
|
|
|
|
|
|
def terminate(signum, frame):
|
|
global terminating
|
|
terminating = True
|
|
|
|
|
|
def main():
|
|
print('Doing initial setup')
|
|
global reloading, terminating
|
|
|
|
# Set up signal handlers.
|
|
print('Setting up signal handlers')
|
|
signal.signal(signal.SIGHUP, reload)
|
|
signal.signal(signal.SIGINT, terminate)
|
|
signal.signal(signal.SIGTERM, terminate)
|
|
|
|
# Do any other setup work here.
|
|
|
|
# Once all setup is done, signal readiness.
|
|
print('Done setting up')
|
|
notify_ready()
|
|
|
|
print('Starting loop')
|
|
while not terminating:
|
|
if reloading:
|
|
print('Reloading')
|
|
reloading = False
|
|
|
|
# Support notifying the manager when reloading configuration.
|
|
# This allows accurate state tracking as well as automatically
|
|
# enabling 'systemctl reload' without needing to manually
|
|
# specify an ExecReload= line in the unit file.
|
|
|
|
notify_reloading()
|
|
|
|
# Do some reconfiguration work here.
|
|
|
|
print('Done reloading')
|
|
notify_ready()
|
|
|
|
# Do the real work here ...
|
|
|
|
print('Sleeping for five seconds')
|
|
time.sleep(5)
|
|
|
|
print('Terminating')
|
|
notify_stopping()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.stdout.reconfigure(line_buffering=True)
|
|
print('Starting app')
|
|
main()
|
|
print('Stopped app')
|