[systemd-devel] directive for executing a script on service failure
George Karakougioumtzis
mad-proffessor at hotmail.com
Wed Feb 11 04:06:10 PST 2015
Since i couldn't find any info on the python's systemd-dbus api to get
the status of the services that i wanted i looked into python-systemd
and made a class (which is far from being ideal i must admit as i am a
python newbie) that monitors the journal for failed services. Class is
based upon info from python-systemd site and a post on stack overflow.
Here it is:
-----------------------------------
#!/usr/bin/python
import systemd
import select
import json
import time
import threading
from systemd import journal
from gi.repository import Notify, GObject
class LogReader():
def __init__(self):
pass
def start_reading(self):
j = journal.Reader()
#j.this_boot(bootid=None)
j.log_level(journal.LOG_INFO)
# j.add_match(_SYSTEMD_UNIT="systemd-udevd.service")
j.seek_tail()
p = select.poll()
p.register(j, j.get_events())
while p.poll():
waiting=j.process()
if waiting == 1 or waiting == 2:
j.get_next()
for entry in j:
#print entry
if 'MESSAGE' in entry:
str2= "entered failed state"
try:
string=entry['MESSAGE'].decode('utf-8')
if string and str2 in string:
Notify.init("myapp_name")
n = Notify.Notification.new("journald:", string)
n.show()
except Exception as e:
raise
def start_threads(self):
for i in range(1,10):
# Instatiates the thread
# (i) does not make a sequence, so (i,)
t = threading.Thread(target=self.start_reading(), args=(i,))
# Sticks the thread in a list so that it remains accessible
thread_list.append(t)
# Starts threads
for thread in thread_list:
thread.start()
thread_list = []
# This blocks the calling thread until the thread whose join() method is
called is terminated.
# From http://docs.python.org/2/library/threading.html#thread-objects
for thread in thread_list:
thread.join()
lr=LogReader()
lr.start_threads()
-------------------------------------------------------
On 02/10/2015 10:53 PM, Lennart Poettering wrote:
> On Fri, 06.02.15 21:23, Mantas Mikulėnas (grawity at gmail.com) wrote:
>
>> On Fri, Feb 6, 2015 at 5:26 PM, George Karakougioumtzis <
>> mad-proffessor at hotmail.com> wrote:
>>
>>> Hi. Congrats for the near perfect job on systemd! I was searching for a
>>> directive to execute a script upon systemd service failure. I would like
>>> to receive desktop notifications about such failures. I stumbled upon
>>> OnFailure and FailureAction but these have hardcoded list of actions?
>> One of those actions is "start an arbitrary unit", which could handle
>> notifications... Unfortunately it doesn't actually pass any failure
>> information to that unit.
>>
>> So, instead, you might have to watch the system
>> log (journal) for unit failure notices. (I would normally have said that
>> the journal makes it easy to filter for them, but quite strangely, these
>> ones don't have a MESSAGE_ID attached...)
> if you use OnFailure= I'd recommend checking the properties of the
> unit that failed instead of checking the journal. i.e. the equivalent
> of "systemctl show -p ..." on the unit that failed...
>
> And yeah, we should define a MESSAGE_ID for unit failure log messages.
>
>>> Any hints how to get notified (with notify-send most likely)?
>> systemd calling notify-send isn't going to happen – as a service, it runs
>> "outside" your desktop session, and has no access to its D-Bus session bus,
>> which tends to be started at a random address. (There might even be several
>> sessions, not just one!) And even considering the future "user bus" plans
>> (which would put the session bus at a known fixed location), the whole idea
>> of having a service inject something into a desktop session is really ugly.
>> Even Microsoft realized that and implemented "session 0 isolation"
>> in VIsta.
> Yes, that's correct. We do not call from lower layers into higher
> layers in systemd. Higher layers should instead subscribe to lower
> layers...
>
>> In other words, such a notifier would need to be started from within your
>> desktop session, connect *to* systemd (either by waiting for signals on the
>> system bus or by watching the journal messages), and idle in background
>> waiting for some unit to fail. With DBus it could be a simple 10-line
>> script, waiting for signals on one bus and calling Notify() on another...
> Another option would be to write a clinet that watches the journal
> constantly, and pops up a notification each time a message with
> LOG_ERR and higer is sent. After all, not only service errors should
> be interesting, all other errors should matter too..
>
> Lennart
>
More information about the systemd-devel
mailing list