You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
5.3 KiB
201 lines
5.3 KiB
#!/usr/bin/perl
|
|
|
|
use strict;
|
|
use warnings;
|
|
use DBI;
|
|
use Sys::Syslog;
|
|
|
|
openlog("acc-cleanup", "ndelay,pid", "daemon");
|
|
$SIG{__WARN__} = $SIG{__DIE__} = sub {
|
|
syslog('warning', "@_");
|
|
};
|
|
|
|
my $config_file = "/etc/ngcp-cleanup-tools/acc-cleanup.conf";
|
|
open(CONFIG, "<", $config_file) or die("Program stopping, couldn't open the configuration file '$config_file'.\n");
|
|
|
|
########################################################################
|
|
|
|
my (%vars, $dbh);
|
|
|
|
sub delete_loop {
|
|
my ($table, $mtable, $col, $mstart) = @_;
|
|
|
|
my $limit = '';
|
|
$vars{batch} && $vars{batch} > 0 and $limit = " limit $vars{batch}";
|
|
|
|
while (1) {
|
|
my $res = $dbh->selectcol_arrayref("select id from $table
|
|
where $col >= ?
|
|
and $col < date_add(?, interval 1 month) $limit",
|
|
undef, $mstart, $mstart);
|
|
|
|
$res or last;
|
|
@$res or last;
|
|
|
|
my $idlist = join(",", @$res);
|
|
$dbh->do("insert into $mtable select * from $table where id in ($idlist)")
|
|
or die("Failed to insert into monthly table $mtable");
|
|
$dbh->do("delete from $table where id in ($idlist)")
|
|
or die("Failed to delete records out of $table");
|
|
}
|
|
}
|
|
|
|
sub archive_dump {
|
|
my ($table) = @_;
|
|
|
|
my $month = $vars{"archive-months"};
|
|
while (1) {
|
|
my $now = time();
|
|
my $bt = $now - int(30.4375 * 86400 * $month);
|
|
my @bt = localtime($bt);
|
|
my $mtable = $table . "_" . sprintf('%04i%02i', $bt[5] + 1900, $bt[4] + 1);
|
|
my $res = $dbh->selectcol_arrayref("show table status like ?", undef, $mtable);
|
|
($res && @$res && $res->[0]) or last;
|
|
$month++;
|
|
if ($vars{"archive-target"} ne '/dev/null') {
|
|
my $target = $vars{"archive-target"} . "/$mtable." . sprintf('%04i%02i%02i%02i%02i%02i', $bt[5] + 1900, $bt[4] + 1, @bt[3,2,1,0]) . ".sql";
|
|
|
|
my @cmd = ('mysqldump');
|
|
$vars{username} and push(@cmd, "-u" . $vars{username});
|
|
$vars{password} and push(@cmd, "-p" . $vars{password});
|
|
$vars{host} and push(@cmd, "-h" . $vars{host});
|
|
push(@cmd, "--opt", $dbh->{private_db}, $mtable);
|
|
|
|
for (@cmd) { s/'/'"'"'/g; $_ = "'$_'" }
|
|
my $cmd = join(' ', @cmd);
|
|
|
|
if (system("$cmd > $target")) {
|
|
unlink($target);
|
|
die("MySQL DUMP of table $mtable into file $target failed\n");
|
|
}
|
|
if ($vars{compress} && $vars{compress} eq 'gzip') {
|
|
if (system("nice gzip -9 $target")) {
|
|
unlink($target, "$target.gz");
|
|
die("Gzipping of dump file $target failed\n");
|
|
}
|
|
}
|
|
}
|
|
$dbh->do("drop table $mtable");
|
|
}
|
|
}
|
|
|
|
sub backup_table {
|
|
my ($table) = @_;
|
|
|
|
for my $cmonth (0 .. ($vars{"backup-retro"} - 1)) {
|
|
my $tmonths = $cmonth + $vars{"backup-months"};
|
|
my $bt = time() - int(30.4375 * 86400 * $tmonths);
|
|
my @bt = localtime($bt);
|
|
my $tstampl = sprintf('%04i-%02i', $bt[5] + 1900, $bt[4] + 1);
|
|
my $tstamp = sprintf('%04i%02i', $bt[5] + 1900, $bt[4] + 1);
|
|
my $mstart = "$tstampl-01 00:00:00";
|
|
|
|
my $mtable = $table . "_$tstamp";
|
|
$dbh->do("create table if not exists $mtable like $table");
|
|
delete_loop($table, $mtable, $vars{"time-column"}, $mstart);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
sub cleanup {
|
|
my ($table) = @_;
|
|
|
|
my $limit = '';
|
|
$vars{batch} && $vars{batch} > 0 and $limit = " limit $vars{batch}";
|
|
my $col = $vars{"time-column"};
|
|
|
|
while (1) {
|
|
my $aff = $dbh->do("delete from $table where $col < date(date_sub(now(), interval ? day)) $limit",
|
|
undef, $vars{"cleanup-days"});
|
|
$aff or die("Unable to delete records from $table");
|
|
$aff == 0 and last;
|
|
}
|
|
}
|
|
|
|
########################################################################
|
|
|
|
my %cmds;
|
|
|
|
$cmds{unset} = sub {
|
|
my ($var) = @_;
|
|
|
|
$var or die("Syntax error in unset command");
|
|
|
|
delete($vars{$var});
|
|
};
|
|
|
|
$cmds{connect} = sub {
|
|
my ($db) = @_;
|
|
|
|
undef($dbh);
|
|
|
|
$db or die("Missing DB name for connect command");
|
|
|
|
my $dbi = "dbi:mysql:$db";
|
|
$vars{host} and $dbi .= ";host=$vars{host}";
|
|
|
|
$dbh = DBI->connect($dbi, $vars{username}, $vars{password});
|
|
$dbh or die("Failed to connect to DB $db");
|
|
|
|
$dbh->{private_db} = $db;
|
|
};
|
|
|
|
$cmds{backup} = sub {
|
|
my ($table) = @_;
|
|
|
|
$table or die("No table name given in backup command");
|
|
$dbh or die("Not connected to a DB in backup command");
|
|
$vars{"time-column"} or die("Variable time-column not set in backup command");
|
|
$vars{"backup-months"} or die("Variable backup-months not set in backup command");
|
|
$vars{"backup-retro"} or die("Variable backup-retro not set in backup command");
|
|
|
|
backup_table($table);
|
|
};
|
|
|
|
$cmds{archive} = sub {
|
|
my ($table) = @_;
|
|
|
|
$table or die("No table name given in archive command");
|
|
$dbh or die("Not connected to a DB in archive command");
|
|
$vars{"archive-months"} or die("Variable archive-months not set in archive command");
|
|
$vars{"archive-target"} or die("Variable archive-target not set in archive command");
|
|
|
|
archive_dump($table);
|
|
};
|
|
|
|
$cmds{cleanup} = sub {
|
|
my ($table) = @_;
|
|
|
|
$table or die("No table name given in backup command");
|
|
$dbh or die("Not connected to a DB in backup command");
|
|
$vars{"time-column"} or die("Variable time-column not set in cleanup command");
|
|
$vars{"cleanup-days"} or die("Variable cleanup-days not set in cleanup command");
|
|
|
|
cleanup($table);
|
|
};
|
|
|
|
while (my $line = <CONFIG>) {
|
|
$line =~ s/^\s*//s;
|
|
$line =~ s/\s*$//s;
|
|
|
|
$line =~ /^#/ and next;
|
|
$line =~ /^$/ and next;
|
|
|
|
if ($line =~ /^([\w-]+)\s*=\s*(\S*)$/) {
|
|
$vars{$1} = $2;
|
|
next;
|
|
}
|
|
|
|
my ($cmd, $rest) = $line =~ /^([\w-]+)(?:\s+(.*?))?$/;
|
|
$cmd or die("Syntax error in config file: '$line'");
|
|
|
|
my $sub = $cmds{$cmd};
|
|
$sub or die("Unrecognized statement '$cmd'");
|
|
|
|
my @rest;
|
|
$rest and @rest = split(/\s+/, $rest);
|
|
|
|
$sub->($rest, \@rest);
|
|
}
|