I’m running a Monit based monitoring solution, but I do not have an email server (that I can use), so when something goes wrong and Monit Alerts is raised, I have no way receive a notification that something is wrong.
So I built a quick notification system, done in Python, that when a Monit detects an error, it notifies me by activating a KDE Notification on my desktop…
The solution that I use is quite simple and quick (Warning it’s an hack…):
My solution uses a python based network server running on my desktop listening for messages, and a python client deployed on the Monit server that sends messages, when called.
In short, the running server on my KDE desktop waits for a connection on a specific port, and when one connection is established it reads any text that comes on the connection payload and displays it using the KDE notification system:
## Monit Desktop Notification Network server import socket import sys import knotify import dbus ## Constants definition HOST = '' # Host IP Address. Empty means that we are the host PORT = 29876 # Listening port. Choose any above 1024. The client must use the same port... ADDR = (HOST,PORT) BUFSIZE = 4096 ## Send notification for the KDE notification system def notify(title, text): knotify = dbus.SessionBus().get_object("org.kde.knotify", "/Notify") knotify.event("warning", "kde", , title, text, , , 0, 0, dbus_interface="org.kde.KNotify") print 'Server Started' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print 'Socket created' # Bind socket to local host and port try: s.bind((HOST, PORT)) except socket.error as msg: print 'Bind failed. Error Code : ' + str(msg) + ' Message ' + msg sys.exit() print 'Socket bind complete' #Start listening on socket s.listen(10) print 'Socket now listening' #now keep talking with the client while 1: #wait to accept a connection - blocking call conn, addr = s.accept() print 'Connected with ' + addr + ':' + str(addr) # Read the message that comes from the monit server. data = conn.recv(1024) # Send the message to the KDE notification system notify("Monit Alarm!", data) s.close()
At the Monit server, I placed the following files at the Monit bin directory: notify.py and notify.sh:
notify.pyfrom socket import * import sys from datetime import datetime HOST = '192.168.1.200' # My machine IP. Change to the IP where the NotifyServe.py is running PORT = 29876 ADDR = (HOST,PORT) cli = socket( AF_INET,SOCK_STREAM) cli.connect((ADDR)) print len(sys.argv) if ( len(sys.argv) > 1 ): message = str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')) + ": " + sys.argv cli.send( message ) else: cli.send("Undefined Alert!") cli.close()
Notify.py receives a message passed as a command line parameter and sends it to the NotifyServer running on the desktop machine.
The notify.sh shell script is a wrapper for the Monit server to call the monit.py script. Keep in mind that you must use absolute paths in every single file, otherwise it won’t work.#!/bin/bash /usr/bin/python2 /home/monitor/monit/bin/notify.py $1
Now on the monitrc file we can change the alert lines from (for example):check program System_status with path "/home/monitor/ShMonitor/SystemStatus.sh" if status !=0 then alert
tocheck program System_status with path "/home/monitor/ShMonitor/SystemStatus.sh" if status !=0 for 15 cycles then exec "/home/monitor/monit/bin/notify.sh SystemStatus_Problem"
I added the for 15 cycles to avoid being flooded with notifications while I solve the issue… But it really depends of the monitoring pooling cycle. Adjust as required.
So, there it is, some code snippets gather across the web, allows me to have Monit notifications right at my desktop :)