#!/usr/bin/perl # Gregg Lain gregg @ MOCHABOMB . COM # 2010-OCT-16 # # This script is distributable under the same terms as Perl itself. # # purgebinarylogs.pl - uses ~root/.my.cnf for root login info. use strict; use warnings; use Getopt::Long; my ($ok, $output, %mysqlprops, @lines, $purgeto, $query, $verbose, $purge, $back, $dir, $logbin) = undef; # init $verbose = $purge = $back = 0; $dir = $logbin = "/tmp"; # exit if no arguments are passed &Help unless (@ARGV); my $results = GetOptions ( "v|verbose" => \$verbose, "p|purge" => \$purge, "d|dir=s" => \$dir, "h|help" => \&Help, "l|logbin=s" => \$logbin, "b|back=i" => \$back); # bail if options are not passed correctly exit 1 unless ($results); # set to defaults if not specified $dir = ($dir =~ /[\w\/\-]{4,}/) ? $dir : "/var/log/mysql"; $logbin = ($logbin =~ /[\w\/\-]{9,}/) ? $logbin : "/var/log/mysql/log-bin.index"; $back = ($back >= 1) ? $back : 3; # set these values %mysqlprops = ( 'mysqldir' => $dir, 'logbin-index' => $logbin, 'files-to-keep' => $back ); # Get the log-bin file listing open(INDEX, "<$mysqlprops{'logbin-index'}") or die "Cannot open $mysqlprops{'logbin-index'}\n"; @lines = ; chomp(@lines); close INDEX; my $n_lines = @lines; print "Go back $back with $n_lines binlogs\n" if ($verbose); # Exit if trying to go further back than what is available if (($n_lines !~ /\d+/) or ($n_lines <= ($back-1)) or ($back < 1)) { print "Cannot go back $back with only $n_lines binlogs\n"; print "Purge option not set\n" unless ($purge); exit(1); } # Go back through the bottom of the array to get the one to purge to # Gotta love negative indexes :) $purgeto = $lines[-$mysqlprops{'files-to-keep'}]; # Remove path... $purgeto =~ s#^.*\/##; print "Purge to: $purgeto\n" if ($verbose); # Build the query $query = 'mysql -e \'purge binary logs to "' . $purgeto . '"\''; print "$query\n" if ($verbose); # If this runs fine, lets purge on. my $testquery = 'mysql -e "show binary logs"'; system("$testquery") == 0 or die "Test query $testquery failed\n";; # Purge only if told to if ($purge) { $output = `$query`; print "$output\n" if ($verbose); } print "\n------- After purging -------\n" if ($verbose); # else tell what would have happened if ($purge != 1) { print "Purge option \"-p\" not set, would have used \n" . $query . "\n"; } # details .. details if ($verbose) { # Get the file listing again, print out.. open(INDEX, "<$mysqlprops{'logbin-index'}") or die "Cannot open $mysqlprops{'logbin-index'}\n"; @lines = ; close INDEX; system("$testquery"); # Build and Print the new log listing... $output .= "Bin Logs:\n"; foreach (@lines) {$output .= `ls -la $_`;} print $output; } sub Help { print << "FINI"; purgebinarylogs.pl - simple MySQL binary log purging.. It goes back N files and purges to that point. Its good to make sure your slave queries are caught up before purging logs. WHY I was manually purging logs every 3-4 weeks when disk space was getting used up. This alleviates this task... Uses the ~/my.cnf file for login information. This was written to run on Linux/Unix machines. USE -v -verbose verbose output -d -dir default is /var/log/mysql -l -logbin default is /var/log/mysql/log-bin.index -p -purge purge the logs -b -back logs to keep; default is 3 -h -help print this help 0. Configure the \%mysqlprops as needed or use command line options 1. Its good to have backups of the binary logs in case things go wrong. 2. run purgebinarylogs.pl -p to purge sample crontab entry # purge binary logs - the two lines below need to be one line in crontab 17 */2 * * * /usr/local/bin/purgebinarylogs.pl -b 7 -p -v >> /var/log/purgebinarylogs.log 2>&1; 3. To adjust binlog file sizes, see mysql docs for max_binlog_size Please send feedback to gregg at mochabomb daht com USE AT YOUR OWN RISK! No warranties express or implied. If this deletes all your data and your shiny Mercedes gets repossesed, I apologize. You have been warned. FINI exit 0; }