On Thu, Feb 13, 2014 at 1:35 PM, Thomas Bächler <thomas@archlinux.org> wrote:
Am 13.02.2014 13:04, schrieb Paul Gideon Dann:
Does anyone know of any standard system for receiving notifications from systemd for unit state changes? I currently use Monit for the monitoring of many processes, and it'll e-mail me when things happen (e.g. a process was restarted). Since switching to systemd, it's felt a bit silly that for several processes, I'm having Monit monitor them simply because systemd is unable to tell me it restarted a unit. Monit isn't actually required to keep those processes alive as it once was, because systemd can do that.
I'd place a bet on the systemd dbus API: IIRC, it exports the state of each unit as a property and then emits the standard org.freedesktop.DBus.Properties.PropertiesChanged signal when the state changes.
So, your task would be to subscribe to that signal and act on it. This could be nicely done in python (and maybe someone has done it already).
Ok... I'll take the chance to practice my DBus abilities... It is a bit long, but it kind of works. Just replace the print() call with your favourite sendmail function and you'll get a notification every time any of the units specified in the command line changes status. HTH. #!/usr/bin/python from gi.repository import GObject import sys import dbus from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) bus = dbus.SystemBus() systemd = bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1') manager = dbus.Interface(systemd, 'org.freedesktop.systemd1.Manager') def GetPropChanged(obj, iface, propName, changes, invalids): if propName in invalids: return obj.Get(iface, propName, dbus_interface=dbus.PROPERTIES_IFACE) elif propName in changes: return changes[propName] else: return None def OnPropChanged(unit, name, iface, changes, invalids): if iface != 'org.freedesktop.systemd1.Unit': return state = GetPropChanged(unit, iface, 'ActiveState', changes, invalids) substate = GetPropChanged(unit, iface, 'SubState', changes, invalids) if state or substate: print('Status changed', name, state, substate) for unitName in sys.argv[1:]: unit = bus.get_object('org.freedesktop.systemd1', manager.GetUnit(unitName)) unit.connect_to_signal('PropertiesChanged', lambda a,b,c : OnPropChanged(unit, unitName, a, b, c), dbus_interface=dbus.PROPERTIES_IFACE) loop = GObject.MainLoop() loop.run()