Skip to content

Instantly share code, notes, and snippets.

@greyson
Created February 2, 2014 16:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greyson/8770516 to your computer and use it in GitHub Desktop.
Save greyson/8770516 to your computer and use it in GitHub Desktop.
Simple, powerful connection monitor
#!/usr/bin/python
DEFAULT_SOUNDFILE="/home/greyson/alerts/S_083772.mp3"
DEFAULT_HOST="209.18.47.61"
import os
import subprocess
import sys
import time
import re
import signal
from datetime import datetime
def get_default_nameserver():
with open( "/etc/resolv.conf", 'r' ) as file:
resolv = file.read()
m = re.search( "^nameserver[ \t]+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)",
resolv, re.MULTILINE )
return m.group( 1 )
class BackgroundSound:
"""
Plays a sound in the background for as long as it is running
"""
def __init__( self, soundfile=DEFAULT_SOUNDFILE ):
self.soundfile = soundfile
self.pid = None
self.devnull = open( os.devnull, 'wb' )
def begin( self ):
self.pid = subprocess.Popen(
["/usr/bin/mplayer", "-noconsolecontrols",
"-really-quiet",
"-loop", "0", self.soundfile ],
stdout=self.devnull,
stderr=self.devnull )
def end( self ):
self.pid.kill()
self.pid = None
def isPlaying( self ):
return self.pid is not None
online = 1
offline = 2
class Stats:
"""
Collects stats to be reported.
"""
def __init__( self ):
self.state = offline
self.current = 0
self.max_online = 0
self.max_offline = 0
self.tot_online = 0
self.tot_offline = 0
self.last_report = 0
# Set up the signal handler.
print( "Monitoring started:",
datetime.now().strftime( "%A, %d %B %Y %H:%M" ) )
signal.signal( signal.SIGINT, self.handler )
def handler( self, num, _ ):
reporttime = time.time()
if (reporttime - self.last_report) < 2:
print( "Quitting monitor" )
sys.exit( 0 )
print( '' )
self.last_report = reporttime
self.print_stats()
return 1
def print_stats( self ):
print( "REPORT AT:",
datetime.now().strftime( "%A, %d %B %Y %H:%M" ) )
# Report the current state (and duration it's been that way)
if self.state == online:
print( "Currently online (%d ticks)" % self.current )
self.max_online = max( self.max_online, self.current )
else:
print( "Currently OFFLINE (%d ticks)" % self.current )
self.max_offline = max( self.max_offline, self.current )
# Report the longest stretches of both connected and
# disconnected states
print( "Maximum down stretch: %d ticks" % self.max_offline )
print( "Maximum up stretch: %d ticks" % self.max_online )
# Report the average uptime for the connection
total = float(self.tot_offline + self.tot_online)
avg_on = (self.tot_online / total * 100)
print( "Average uptime (percent):", avg_on )
def offline( self ):
self.tot_offline += 1
print( 'X', end='' )
sys.stdout.flush()
if self.state == online:
self.max_online = max( self.max_online,
self.current )
self.state = offline
self.current = 0
self.current += 1
def online( self ):
self.tot_online += 1
print( '.', end='' )
sys.stdout.flush()
if self.state == offline:
self.max_offline = max( self.max_offline,
self.current )
self.state = online
self.current = 0
self.current += 1
class FullReporter:
def __init__( self ):
self.bs = BackgroundSound()
self.s = Stats()
self.log = open( "uptime.log", 'a' )
self.log.write( "start " + datetime.now().isoformat() + "\n" )
self.log.flush()
def exiting( self ):
self.log.write( "\nend " + datetime.now().isoformat() + "\n" )
self.log.flush()
def online( self ):
self.s.online()
self.log.write( '.' )
if self.bs.isPlaying():
self.bs.end()
def offline( self ):
self.s.offline()
self.log.write( 'X' )
if not self.bs.isPlaying():
self.bs.begin()
class PingCheck:
"""
Pings a remote host to check the current packet loss
"""
def __init__( self, host=DEFAULT_HOST ):
self.host = host
self.pattern = re.compile( b"([0-9]+)% packet loss" )
def check( self ):
output = subprocess.Popen(
[ "/usr/bin/ping", "-c", "5", "-i", ".2", "-q",
self.host ],
stdout=subprocess.PIPE ).communicate()[0]
m = self.pattern.search( output, re.MULTILINE )
return int( m.group( 1 ) )
if __name__ == "__main__":
host = get_default_nameserver()
print( "Default host is " + host )
p = PingCheck( host )
r = FullReporter()
try:
while True:
if p.check() != 0:
r.offline()
else:
r.online()
time.sleep( 5 )
except SystemExit:
r.exiting()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment