#!/usr/bin/env python2.4 # # $Id: findinactive.py,v 1.2 2006/02/20 16:39:56 jschauma Exp $ # # mighty assumptions: # an account is inactive if a user has not accessed or modified any files # since 'cutoff' # # every subdirectory under /home is that of a user # # # defaults: # /home # cutoff date = today - 1 year # exclude files: none # # cutoff-date given ? # exclude files given ? import getopt import os import pwd import time import re import string import sys EXIT_ERROR = 1 EXIT_SUCCESS = 0 HOMEROOT = "/home" TODAY = time.time() CUTOFFDIFF = 31556926 CUTOFFDATE = 0 def usage(val=0): print 'Usage: %s [-c|--cutoff] [-h|--help] [-r|--root]' % sys.argv[0] print '\t-c,--cutoff \tspecify cutoff date in format [0-9]+[smhdMY]' print '\t-h,--help \tshow this help and exit' print '\t-r,--root \tspecify parent of users\' $HOME (default: /home)' sys.exit(val) def init(): """initializes all required variables""" global CUTOFFDATE CUTOFFDATE = (TODAY - CUTOFFDIFF) def parseDate(date): """parse a given date and turn it into seconds since epoch""" last = date[-1] val = date[:-1] if not re.match('^[smhdMY]$', last): raise TypeError if not re.match('^[0-9]+$', val): raise TypeError rval = string.atoi(val) if last == "s": return rval elif last == "m": return (rval * 60) elif last == "h": return (rval * 60 * 60) elif last == "d": return (rval * 60 * 60 * 24) elif last == "M": return (rval * 60 * 60 * 24 * 30) elif last == "Y": return (rval * 60 * 60 * 24 * 30 * 12) def parseOpts(): global HOMEROOT global CUTOFFDATE global CUTOFFDIFF try: opts, args = getopt.getopt(sys.argv[1:], "c:hr:", ["cutoff", "help", "root"]) except getopt.GetoptError: usage(EXIT_ERROR) for o, a in opts: if o in ("-c", "--cutoff"): try: CUTOFFDIFF = parseDate(a) CUTOFFDATE = (TODAY - CUTOFFDIFF) except TypeError: print '%s: invalid date given (\'%s\')' % (sys.argv[0], a) print usage(EXIT_ERROR) if o in ("-h", "--help"): usage() if o in ("-r", "--root"): HOMEROOT = a def processHomeDir(uname, dirname, fnames): for f in fnames: path = os.path.join(dirname, f) sb = os.stat(path) # traversing the directory accesses it, so ignore if os.path.isdir(path): continue if sb.st_mtime > CUTOFFDATE or sb.st_atime > CUTOFFDATE: raise StopIteration def main(): global HOMEROOT users = [] for entry in os.listdir(HOMEROOT): try: uid = pwd.getpwnam(entry) homeDir = os.path.join(HOMEROOT, entry) try: os.path.walk(homeDir, processHomeDir, entry) users.append(entry) except StopIteration: pass except KeyError: print 'no such user %s' % entry for u in users: print 'inactive: %s' % u return def cleanup(): return if __name__ == "__main__": init() parseOpts() main() cleanup()