#!/usr/bin/python3 import sys import os import math import subprocess def usage(): m = '''Usage: dfcheck [-n]''' print(m) ############################################################################### class dfcheck_t: addr = 'root@example.com' subject = 'DISK FULL ALERT' limit = 85 def __init__(self): self.sendmail = True un = os.uname() self.host = un.nodename def run(self): try: overs = self.findOvers() if overs: self.notify(overs) except Exception as ex: return -1 return 0 def findOvers(self): rv = [] for part in self.getParts(): tup = self.getUsed(part) if max(tup) >= self.limit: rv.append((part, *tup)) return rv def notify(self, overs): msg = 'Host: %s\n\n' % self.host for over in overs: s = '%3d%% blocks, %3d%% files - %s\n' % (over[1], over[2], over[0]) msg += s if not self.sendmail: print(msg) return subj = self.subject + ' ' + self.host args = ['/usr/bin/mailx', '-s', subj, self.addr] res = subprocess.Popen(args, stdin = subprocess.PIPE, stdout = subprocess.DEVNULL, stderr = subprocess.DEVNULL) res.stdin.write(msg.encode('utf-8')) res.stdin.close() res.wait() def getParts(self): rv = [] fil = open('/proc/mounts') for lin in fil: exp = lin.split() if exp[0].startswith('/'): rv.append(exp[1]) fil.close() return rv def getUsed(self, pth): # try to match df output, even though ordinary users can't use all 100% rec = os.statvfs(pth) bpct = math.ceil(100.0 * (rec.f_blocks - rec.f_bfree) / rec.f_blocks) fpct = math.ceil(100.0 * (rec.f_files - rec.f_ffree) / rec.f_files) return (bpct, fpct) ############################################################################### def main(args = None): if args is None: args = sys.argv[1:] dfc = dfcheck_t() try: while args and args[0].startswith('-'): arg = args.pop(0) if arg == '-n': dfc.sendmail = False else: raise RuntimeError('unknown option ' + arg) if args: raise RuntimeError('too many arguments') except Exception as ex: usage() print(ex) return 1 res = dfc.run() if res < 0: return 1 return 0 if __name__ == "__main__": sys.exit(main()) ############################################################################### # Local Variables: # mode: indented-text # indent-tabs-mode: nil # End: