#!/p4/common/perl/bin/perl -w #============================================================================== # Copyright and license info is available in the LICENSE file included with # the Server Deployment Package (SDP), and also available online: # https://swarm.workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE #------------------------------------------------------------------------------ # For a summary of command line options, run: p4pcm.pl -h # This runs on Unix/Linux systems only. # Log file is p4pcm.log, in $LOGS dir. use strict; use File::Find; use File::Basename; use Getopt::Long; use POSIX; #------------------------------------------------------------------------------ # Initialization #------------------------------------------------------------------------------ BEGIN { $main::ThisScript = basename($0); $main::Version = "1.1.3"; } #------------------------------------------------------------------------------ # Prototypes for local functions. #------------------------------------------------------------------------------ sub usage(); sub getDriveSpace($;); #------------------------------------------------------------------------------ # Declarations #------------------------------------------------------------------------------ # If $Freespace is less than $ThresholdLow, then start deleting files. # $ThresholdHigh is the amount of diskspace we want available/free constantly. # They are specified in kilobyte units. my $AcctTime; my $TopDir; my $ThresholdLow = 10485760; # 10GB my $ThresholdHigh = 20971520; # 20GB my $TotalSize; my $Freespace; my $Timestamp; my $Datestamp; my @RmList; my $RmFile; my @DateSorted; my %Oldest; #------------------------------------------------------------------------------ # Function: usage() # Displays usage message. #------------------------------------------------------------------------------ sub usage () { print "\nUsage:\n $main::ThisScript [-d \"proxy cache dir\"] [-tlow <low_threshold>] [-thigh <high_threshold>] [-n] or $main::ThisScript -h This utility removes files in the proxy cache if the amount of free disk space falls below the low threshold (default 10GB). It removes files (oldest first) until the high threshold is (default 20GB) is reached. Specify the thresholds in kilobyte units (kb). The '-d \"proxy cache dir\"' argument is required unless \$P4PCACHE is defined, in which case it is used. The log is \$LOGS/p4pcm.log if \$LOGS is defined, else p4pcm.log in the current directory. Use '-n' to show what files would be removed. "; exit 1;; } #------------------------------------------------------------------------------ # Function getDriveSpace($TopDir) # Returns a 2-element array containing $totalspace and $Freespace, i.e. # returns ($totalspace, $Freespace). #------------------------------------------------------------------------------ sub getDriveSpace($;) { my ($TopDir) = @_; my $totalSpace; my $freeSpace; my $dirInfo; my $junk; # Run 'df -k $TopDir', and extract the total and available space values, # using $junk to ignore extranneous information. $dirInfo = `df -k $TopDir`; $dirInfo =~ s/^.*?\n//; # Zap the header line. $dirInfo =~ s/\s+/,/gs; # Replace whitespace with comma as field delimiter. ($junk, $totalSpace, $junk, $freeSpace, $junk, $junk) = split (',',$dirInfo); return ($totalSpace, $freeSpace); } #------------------------------------------------------------------------------ # Parse command line. #------------------------------------------------------------------------------ Getopt::Long::config "no_ignore_case"; Getopt::Long::config "auto_abbrev"; GetOptions(\%main::CmdLine, "help", "noop", "dir=s", "tlow=s", "thigh=s") or die "\nUsage Error: Unrecognized argument.\n"; # Validate command line arguments. usage() if $main::CmdLine{'help'}; # The '-d <TopDir>' argument is required unless P4PCACHE is defined in the # shell environment. if ($main::CmdLine{'dir'}) { $TopDir = $main::CmdLine{'dir'}; } elsif ($ENV{P4PCACHE}) { $TopDir = $ENV{P4PCACHE}; } else { usage (); } $ThresholdLow = $main::CmdLine{'tlow'} if ($main::CmdLine{'tlow'}); $ThresholdHigh = $main::CmdLine{'thigh'} if ($main::CmdLine{'thigh'}); #------------------------------------------------------------------------------ # Main Program. #------------------------------------------------------------------------------ $Datestamp = strftime("\%Y-\%m-\%d",localtime); $Timestamp = strftime("\%H:\%M:\%S",localtime); my ($name, $dir, $ext) = fileparse($0, '\..*'); my $logfile; if ($ENV{LOGS}) { $logfile = "$ENV{LOGS}/$name.log"; } else { $logfile = "$name.log"; } open (LOG, ">>$logfile"); print LOG "==============================================================================\n"; print LOG "Started $main::ThisScript v$main::Version at $Datestamp $Timestamp\n"; # Check if $TopDir exists and that it's a directory. if (-e $TopDir && -d $TopDir) { # Find the total amount of free space in $TopDir. ($TotalSize, $Freespace) = getDriveSpace($TopDir); print LOG "Free Space = $Freespace, Low space threshold = $ThresholdLow.\n"; # compare $Freespace to $ThresholdLow if ( $Freespace < $ThresholdLow ) { # while $Freespace is less than $ThresholdHigh # Find oldest file based on "Date Modified" find (sub {$Oldest{$File::Find::name} = -M if -f;}, $TopDir); @DateSorted = sort {(stat($a))[9] <=> (stat($b))[9] } keys %Oldest; while ( $Freespace < $ThresholdHigh ) { $RmFile = shift @DateSorted; last unless ($RmFile); $Freespace += (stat($RmFile))[7]; push(@RmList, $RmFile); } # if @RmList exists, delete it + log if ( @RmList ) { # record the files that will be deleted print LOG "File \t Size \t Accessed\n"; foreach $RmFile ( @RmList ) { $AcctTime = (stat($RmFile))[9]; print LOG "$RmFile \t " . (stat($RmFile))[7] . "\t" . scalar(localtime($AcctTime)) . "\n"; } # Delete files to free space. if ($main::CmdLine{'noop'}) { print LOG "NO-OP: The following files would have been deleted:\n"; foreach $RmFile (@RmList) { print LOG "$RmFile\n"; } } else { print LOG "Files deleted:\n"; foreach $RmFile (@RmList) { unlink $RmFile or print LOG "ERROR: File not deleted:\n$RmFile\n"; } } } } else { # log: There is enough free space in $TopDir until next time print LOG "No files need to be deleted.\n"; } } else { print LOG "\nError: The cache directory [$TopDir] does not exist or is not a directory. Aborting.\n"; } # Stop logging. $Datestamp = strftime("\%Y-\%m-\%d",localtime); $Timestamp = strftime("\%H:\%M:\%S",localtime); print LOG "\nCompleted at $Datestamp $Timestamp.\n"; close(LOG);
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#10 | 29401 | C. Thomas Tyler |
Released SDP 2022.2.29399 (2023/02/06). Copy Up using 'p4 copy -r -b perforce_software-sdp-dev'. |
||
#9 | 28198 | Catherine Louie | #review Correcting values for "$ThresholdLow" and "$ThresholdHigh". | ||
#8 | 27761 | C. Thomas Tyler |
Released SDP 2020.1.27759 (2021/05/07). Copy Up using 'p4 copy -r -b perforce_software-sdp-dev'. |
||
#7 | 27331 | C. Thomas Tyler |
Released SDP 2020.1.27325 (2021/01/29). Copy Up using 'p4 copy -r -b perforce_software-sdp-dev'. |
||
#6 | 25596 | C. Thomas Tyler |
Released SDP 2019.2.25594 (2019/05/02). Copy Up using 'p4 copy -r -b perforce_software-sdp-dev'. |
||
#5 | 21748 | erikf |
Threshold values in bytes are compared to 'df -k' ouptput which is kilobytes. This is wrong. Change the default thresholds to 10 and 20G represented in KBytes not Bytes. Added note to usage to specify thresholds in KBytes Good stuff! Thanks! |
||
#4 | 19414 | C. Thomas Tyler | Released SDP/MultiArch/2016.1/19410 (2016/05/17). | ||
#3 | 15856 | C. Thomas Tyler |
Replaced the big license comment block with a shortened form referencing the LICENSE file included with the SDP package, and also by the URL for the license file in The Workshop. |
||
#2 | 12171 | Russell C. Jackson (Rusty) | Merge in changes to remove the need for p4master_run. | ||
#1 | 10148 | C. Thomas Tyler | Promoted the Perforce Server Deployment Package to The Workshop. |