PDA

View Full Version : find old .deb's on your Debian system


Strike
09-19-2002, 10:37 PM
I whipped up a script that does the following:

1. Obtains the names of all installed packages (if I used python-apt I could probably do this better)
2. Looks through the list of files that each package "owns" on your system, and stores their atime and mtime (access time and modification time) with that package
3. Then it looks through each package and finds which have nothing but atimes and mtimes older than X number of years/months/days/etc.

Here is a link to my current working version (if I update it, it will be updated here): http://strike.homelinux.org/~ddipaolo/python/apt-oldpkgs/apt_oldpkgs.py

And here is a snapshot of what I have:

#!/usr/bin/env python

import os
import os.path
import stat
import time

_minute = 60
_hour = 60 * _minute
_day = 24 * _hour
_month = 30 * _day
_year = 365 * _day

LISTFILES_DIR = "/var/lib/dpkg/info"
LISTFILES_SUFFIX = ".list"
OLDDATE = time.time() - _year # Anything older than 1 year is considered "old"

class deb_file(file):
def __init__(self, name, mode):
file.__init__(self, name, mode)
self.atime = os.stat(self.name)[stat.ST_ATIME]
self.mtime = os.stat(self.name)[stat.ST_MTIME]

def is_older_than(self, date):
# date is in good ol' UNIX time - number of seconds since the epoch,
# and we compare to the atime and mtime of the file, if both of them
# are older, then we return true. Otherwise it's false.
return date > self.atime and date > self.mtime

class deb_package:
def __init__(self, name):
self.name = name
self.listfile_name = "%s/%s%s" % (LISTFILES_DIR, name, LISTFILES_SUFFIX)
self.filenames = self.get_files()

def get_files(self):
# We want to look at only leaves of the directory tree that are in the
# .list file (that is, only files and not directories)
actual_files = []
listfile = file(self.listfile_name, "r")
for filename in listfile.readlines():
filename = filename.strip()
if not os.path.isdir(filename):
actual_files.append(filename)
listfile.close()
return actual_files

def is_older_than(self, date):
# Returns true if all the atimes and mtimes of the files in this
# package are older than date (seconds since the epoch)
for pkg_filename in self.filenames:
try:
pkg_file = deb_file(pkg_filename, "r")
except IOError:
return 0 # Permission denied
if not pkg_file.is_older_than(date): return 0
pkg_file.close()
return 1

def get_package_names():
# For some weird reason (maybe I'm misunderstanding scope within for
# loops), I couldn't just use orig_list.remove on anything NOT ending with
# LISTFILES_SUFFIX, as it wouldn't remove everything appropriate and I
# think it actually removed some stuff I didn't want it to.
pkg_list = []
orig_list = os.listdir(LISTFILES_DIR)
for filename in orig_list:
if filename.endswith(LISTFILES_SUFFIX):
filename = filename[:len(filename)-len(LISTFILES_SUFFIX)]
if filename not in pkg_list:
pkg_list.append(filename)
return pkg_list

if __name__ == "__main__":
old_pkgs = []
pkg_list = get_package_names()
for pkg_name in pkg_list:
new_pkg = deb_package(pkg_name)
print "checking " + new_pkg.name
if new_pkg.is_older_than(OLDDATE):
old_pkgs.append(new_pkg)

print "The following packages were found to be old:"
for pkg in old_pkgs:
print "\t" + pkg.name

Strike
09-19-2002, 10:39 PM
Oh, one other thing, I'm not quite sure the logic I'm using is sound - atime and mtime really only seem to be updated whenever you actually CHANGE the file (though access hints to me that it's any time any program uses it), so this may give you some "false positives" on what old packages you have installed

kmj
09-20-2002, 10:33 AM
This is damned cool, and as strike already knows, useful for a guy like me who never keeps track of his packages. I'm going to run this this weekend to see if there's anything I should get rid of... hmm, probably have to modify it a bit to take command line arguments..

so I can do something like olddebs month 2 for two-month old packages, for example.

Strike
09-20-2002, 11:51 AM
Any changes you make, I'll take patches for :)

I have thought about making the change you have suggested, actually, and may work it in. I may also accept a listing of packages from a file or from stdin.