#!/usr/bin/perl # # Name: spacewalk-orphaned-files # Author: Alan Evans # Version: 0.01 # Date: Oct-27-2010 # # Description: # Check the /var/satellite directory for files that are not in the RHN database # and report them to STDERR # # Example: # spacewalk-orphaned-files 2>/tmp/orphanedfiles.txt # # cd /var/satellite # cut -d':' -f2 /tmp/orphanedfiles.txt | xargs -l1 rm -f # # Note: It is highly advisable that you review the results of this script # before doing anything drastic like removing files it reports. # You've been warned! $|=1; use strict; use DBI; use DBD::Oracle; use Getopt::Long; our $RHNUSER = 'rhnsat'; our $RHNPASS = 'rhnsat'; our $RHNDB = 'rhnsat'; our $RHNDIR = '/var/satellite'; my $result = GetOptions( "usage" => \&usage, "user=s" => \$RHNUSER, "pass=s" => \$RHNPASS, "db=s" => \$RHNDB, "dir=s" => \$RHNDIR, ); # Make sure that we're looking in a sensible place die ("Are you sure '$RHNDIR' is the right place?") unless ( -d "$RHNDIR/redhat"); # Connect to the RHN database our $dbh = DBI->connect("dbi:Oracle:$RHNDB", $RHNUSER, $RHNPASS) or die( $DBI::errstr . "\n" ); # Prepare the SELECT statement. I used a UNION to simplify the search process # for RPMS and SRPMS. In testing using a UNION had no negative impact on # performance. our $sth = $dbh->prepare("SELECT ID FROM RHNSAT.RHNPACKAGE WHERE PATH = ? UNION SELECT ID FROM RHNSAT.RHNPACKAGESOURCE WHERE PATH = ?") or die ($DBI::errstr . "\n"); # Setup some counters for showing progress our $processed = 0; our $orphaned = 0; # usage() # Print a bit of usage info and exit sub usage { print "usage: $0 [options]\n"; print < satellite database username (default: $RHNUSER) --pass satellite database password (default: $RHNPASS) --db satellite database name (default: $RHNDB) --dir satellite package directory (default: $RHNDIR) --usage this EOF exit; } # process_dir($dir) # $dir - the directory to descend into # Loop through the items in $dir and if the item is a directory descend into it # if the item is a file then send that off to process_file. sub process_dir { my $dir = shift; opendir (my $dh, $dir); while ($_ = readdir $dh) { next if ($_ eq ".." || $_ eq "."); my $path = "$dir/$_"; if ( -f "$path" ) { process_file("$path"); } elsif ( -d "$path") { process_dir($path); } } closedir($dh); } # process_file($file) # $file - the full path of the file to check the database for # Check that file as relative to $RHNDIR is in the RHN database, if not # incriment $orphaned and print the relative name to STDERR. sub process_file { my $file = shift; # exit if ($processed > 1000); # Make $file relative to $RHNDIR $file = substr($file, length($RHNDIR) + 1); $processed++; $sth->execute($file, $file) or die($DBI::errstr . "\n"); $sth->fetch(); # If we got more or less than one record then something went wrong if ($sth->rows != 1) { print STDERR "\nnot in db: $file\n"; $orphaned++; } # I like to know that my script is doing something... printf "\rprocessed/orphaned %d/%d", $processed, $orphaned; } # Kick this thing off process_dir("$RHNDIR/redhat");