Commit 7f74758b authored by Nigel Kukard's avatar Nigel Kukard
Browse files

Added logging

parent e3fd3cd1
......@@ -41,7 +41,7 @@ use MIME::Base64;
my $VERSION = "0.0.7";
my $VERSION = "0.0.8";
# System dirs we don't care about
my @defaultSystemExcl = ("/dev","/run","/proc","/sys","/tmp","/var/tmp");
# These should be backed up separately
......@@ -57,6 +57,14 @@ my %config;
# Backup constants
use constant {
LOG_DEBUG => 1,
LOG_INFO => 2,
LOG_NOTICE => 3,
LOG_WARNING => 4,
LOG_ERROR => 5
};
use constant {
ST_FILE_CHANGED => 1,
ST_DIR_NEW => 2,
......@@ -77,6 +85,7 @@ GetOptions(\%optctl,
"help",
"config=s",
"log-level=i",
"backup",
"compress:s",
......@@ -147,6 +156,15 @@ if (defined($optctl{'config'})) {
}
}
# Check logging options
if (!defined($config{'log-level'})) {
if (!defined($optctl{'log-level'})) {
$config{'log-level'} = LOG_NOTICE;
} else {
$config{'log-level'} = $optctl{'log-level'};
}
}
# Setup config defaults...
if (!defined($config{'compress'})) {
# Choose default compression method
......@@ -274,12 +292,12 @@ sub backup
# Check if this dir should be backed up or not....
if ( -f "$source/$path/.nodbackup" ) {
printLog("S: Path '[$source]/($path)' EXCLUDED from backup with .nodbackup\n");
printLog(LOG_INFO,"S: Path '[$source]/($path)' EXCLUDED from backup with .nodbackup\n");
return ();
}
# Exclude trash folders
if ( "$source/$path" =~ /(\.Trash-[0-9]{4})$/) {
printLog("S: Path '[$source]/($path)' EXCLUDED from backup, Linux trash folder\n");
printLog(LOG_INFO,"S: Path '[$source]/($path)' EXCLUDED from backup, Linux trash folder\n");
return ();
}
......@@ -299,7 +317,7 @@ sub backup
my $testPath = File::Spec->rel2abs("$sysdir/$excl");
# Check...
if ("/$path" eq $testPath) {
printLog("S: Path '[$source]/($path)' is a system directory, ignoring files\n");
printLog(LOG_INFO,"S: Path '[$source]/($path)' is a system directory, ignoring files\n");
$doBackup{$path} |= ST_DIR_SYS;
return ();
}
......@@ -312,7 +330,7 @@ sub backup
my $testPath = File::Spec->rel2abs("$sysdir/$excl");
# Check...
if ("/$path" eq $testPath) {
printLog("S: Path '[$source]/($path)' is a data directory, ignoring files\n");
printLog(LOG_INFO,"S: Path '[$source]/($path)' is a data directory, ignoring files\n");
$doBackup{$path} |= ST_DIR_SYS;
return ();
}
......@@ -324,7 +342,7 @@ sub backup
foreach my $item (@{$config{'exclude-path'}}) {
# Check...
if ("/$path" =~ $item) {
printLog("S: Path '[$source]/($path)' is an excluded path, ignoring files\n");
printLog(LOG_INFO,"S: Path '[$source]/($path)' is an excluded path, ignoring files\n");
$doBackup{$path} |= ST_DIR_SYS;
return ();
}
......@@ -332,15 +350,13 @@ sub backup
# Check if this dir exists on the backup, if not we need to back it up obviously...
if ( ! -d "$dest/$path") {
# printLog("B: Path '[$dest]/($path)' does not exist\n");
$doBackup{$path} |= ST_DIR_NEW;
# This can probably only be because a backup was continued
} elsif ( ! -f "$dest/$path/.dbackup-state" ) {
# First backup will never have the main dir .dbackup-state file existing
if ($path ne "") {
print(STDERR "WARNING: State file '$dest/$path/.dbackup-state' does not exist\n");
printLog(LOG_WARNING,"State file '$dest/$path/.dbackup-state' does not exist\n");
}
# printLog("B: Path '[$dest]/($path)' needs to be backed up\n");
$doBackup{$path} |= ST_DIR_NEW;
}
......@@ -351,7 +367,7 @@ sub backup
# Check we have at least the version attribute
if (!defined($origPathAttribs{$path}) || !defined($origPathAttribs{$path}->{'dbackup.version'})) {
print(STDERR "ERROR: No dbackup version information found in '$source/$path/.dbackup-state', IGNORING\n");
printLog(LOG_ERROR,"No dbackup version information found in '$source/$path/.dbackup-state', IGNORING\n");
delete($origDirList{$path});
delete($origFileList{$path});
}
......@@ -368,7 +384,7 @@ sub backup
foreach my $filter (@{$config{'exclude-file'}}) {
# Check for match
if ($item =~ $filter) {
# printLog("S: Path '[$source]/($path)/$item' matches file exclude filter, ignoring\n");
printLog(LOG_INFO,"S: Path '[$source]/($path)/$item' matches file exclude filter, ignoring\n");
# XXX: NK - If this ws backed up before and now not, dir has changed?
$match = 1;
last;
......@@ -417,7 +433,7 @@ sub backup
# Ok, lets see whats going on with the dir
if (!defined($origDirList{$path}->{$item})) {
# printLog("S: Directory '[$source]/($path)/$item' is new\n");
printLog(LOG_DEBUG,"S: Directory '[$source]/($path)/$item' is new\n");
$doBackup{$path} |= ST_DIR_CHANGED;
# Check if mtime matches
......@@ -425,28 +441,28 @@ sub backup
!defined($origDirList{$path}->{$item}->{'mtime'}) ||
$origDirList{$path}->{$item}->{'mtime'} ne $mtime
) {
printLog("S: Directory '[$source]/($path)/$item' was modified\n");
printLog(LOG_DEBUG,"S: Directory '[$source]/($path)/$item' was modified\n");
$doBackup{$path} |= ST_DIR_CHANGED;
# Check if uid matches
} elsif (
!defined($origDirList{$path}->{$item}->{'uid'}) ||
$origDirList{$path}->{$item}->{'uid'} ne $uid
) {
printLog("S: Directory '[$source]/($path)/$item' UID was changed\n");
printLog(LOG_DEBUG,"S: Directory '[$source]/($path)/$item' UID was changed\n");
$doBackup{$path} |= ST_DIR_CHANGED;
# Check if gid matches
} elsif (
!defined($origDirList{$path}->{$item}->{'gid'}) ||
$origDirList{$path}->{$item}->{'gid'} ne $gid
) {
printLog("S: Directory '[$source]/($path)/$item' GID was changed\n");
printLog(LOG_DEBUG,"S: Directory '[$source]/($path)/$item' GID was changed\n");
$doBackup{$path} |= ST_DIR_CHANGED;
# Check if mode matches
} elsif (
!defined($origDirList{$path}->{$item}->{'mode'}) ||
$origDirList{$path}->{$item}->{'mode'} ne $mode
) {
printLog("S: Directory '[$source]/($path)/$item' MODE was changed\n");
printLog(LOG_DEBUG,"S: Directory '[$source]/($path)/$item' MODE was changed\n");
$doBackup{$path} |= ST_DIR_CHANGED;
}
......@@ -468,7 +484,7 @@ sub backup
# Check if file does not exists on backup
if (!defined($origFileList{$path}->{$item})) {
if (($doBackup{$path} & ST_DIR_NEW) != ST_DIR_NEW) {
printLog("S: File '[$source]/($path)/$item' is new\n");
printLog(LOG_DEBUG,"S: File '[$source]/($path)/$item' is new\n");
}
$state |= ST_FILE_NEW;
......@@ -477,7 +493,7 @@ sub backup
!defined($origFileList{$path}->{$item}->{'size'}) ||
$origFileList{$path}->{$item}->{'size'} ne $size
) {
printLog("S: File '[$source]/($path)/$item' has different size\n");
printLog(LOG_DEBUG,"S: File '[$source]/($path)/$item' has different size\n");
$state |= ST_FILE_CHANGED;
#
......@@ -488,7 +504,7 @@ sub backup
# !defined($origFileList{$path}->{$item}->{'ctime'}) ||
# $origFileList{$path}->{$item}->{'ctime'} ne $ctime
# ) {
# printLog("S: File '[$source]/($path)/$item' was recreated\n");
# printLog(LOG_DEBUG,"S: File '[$source]/($path)/$item' was recreated\n");
# $state |= ST_FILE_CHANGED;
# Check if mtime matches
......@@ -496,7 +512,7 @@ sub backup
!defined($origFileList{$path}->{$item}->{'mtime'}) ||
$origFileList{$path}->{$item}->{'mtime'} ne $mtime
) {
printLog("S: File '[$source]/($path)/$item' was modified\n");
printLog(LOG_DEBUG,"S: File '[$source]/($path)/$item' was modified\n");
$state |= ST_FILE_CHANGED;
# Check if uid matches
......@@ -504,7 +520,7 @@ sub backup
!defined($origFileList{$path}->{$item}->{'uid'}) ||
$origFileList{$path}->{$item}->{'uid'} ne $uid
) {
printLog("S: File '[$source]/($path)/$item' UID was changed\n");
printLog(LOG_DEBUG,"S: File '[$source]/($path)/$item' UID was changed\n");
$state |= ST_FILE_ATTR_CHANGED
# Check if gid matches
......@@ -512,7 +528,7 @@ sub backup
!defined($origFileList{$path}->{$item}->{'gid'}) ||
$origFileList{$path}->{$item}->{'gid'} ne $gid
) {
printLog("S: File '[$source]/($path)/$item' GID was changed\n");
printLog(LOG_DEBUG,"S: File '[$source]/($path)/$item' GID was changed\n");
$state |= ST_FILE_ATTR_CHANGED;
# Check if mode matches
......@@ -520,7 +536,7 @@ sub backup
!defined($origFileList{$path}->{$item}->{'mode'}) ||
$origFileList{$path}->{$item}->{'mode'} ne $mode
) {
printLog("S: File '[$source]/($path)/$item' MODE was changed\n");
printLog(LOG_DEBUG,"S: File '[$source]/($path)/$item' MODE was changed\n");
$state |= ST_FILE_ATTR_CHANGED;
}
......@@ -552,7 +568,7 @@ sub backup
# Compare the two file lists, we know what was added, lets see if anything was removed
foreach my $fname (keys %{$origFileList{$path}}) {
if (!defined($srcFileList{$path}->{$fname})) {
printLog("File '[$source]/($path)/$fname' removed\n");
printLog(LOG_DEBUG,"File '[$source]/($path)/$fname' removed\n");
$doBackup{$path} |= ST_FILE_CHANGED;
}
}
......@@ -564,7 +580,7 @@ sub backup
# Check if we need to backup this dir
if (($doBackup{$path} & ST_FILE_CHANGED) == ST_FILE_CHANGED) {
printLog("B: Path '[$source]/$path' backing up\n");
printLog(LOG_INFO,"B: Path '[$source]/$path' backing up\n");
# If we not backing up a system dir, we create a manifest and backup the files
if (($doBackup{$path} & ST_DIR_SYS) != ST_DIR_SYS) {
......@@ -672,16 +688,16 @@ sub backup
@tarArgs
);
if ($? == -1) {
printLog(" - Failed to execute: $!\n");
printLog(LOG_ERROR,"Failed to execute: $!\n");
exit 1;
} elsif ($? & 127) {
printLog(" - Child died with signal %d\n",($? & 127));
printLog(LOG_ERROR,"Child died with signal %d\n",($? & 127));
exit 1;
} else {
my $retcode = $? >> 8;
# If tar died, lets die too
if ($retcode == 2) {
print(STDERR "ERROR: tar died with error code $retcode\n");
printLog(LOG_ERROR,"tar died with error code $retcode\n");
exit 1;
}
}
......@@ -711,7 +727,7 @@ sub backup
$newPathAttribs{$path}->{'revision'} = 0;
}
# printLog("B: Writing state '[$source]/$path' - revision ".$newPathAttribs{$path}->{'revision'}."\n");
printLog(LOG_DEBUG,"B: Writing state '[$source]/$path' - revision ".$newPathAttribs{$path}->{'revision'}."\n");
# Write out state, we do this AFTER we have backed up, so if we stopped, we can just continue
my $gz = gzopen("$dest/$path/.dbackup-state","wb")
......@@ -775,19 +791,19 @@ sub backup
delete($origFileList{$path});
}
printLog("BACKUP START: $source => $dest\n");
printLog("Compression: ".$config{'compress'}."\n");
printLog(LOG_NOTICE,"BACKUP START: $source => $dest\n");
printLog(LOG_INFO,"Compression: ".$config{'compress'}."\n");
# Check if we excluding system files
if ($config{'exclude-system'}) {
printLog("Exclude System Base: ".join(", ",@{$config{'system-base'}})."\n");
printLog("Exclude System Dirs: ".join(", ",@defaultSystemExcl,@{$config{'system-dir'}})."\n");
printLog(LOG_NOTICE,"Exclude System Base: ".join(", ",@{$config{'system-base'}})."\n");
printLog(LOG_NOTICE,"Exclude System Dirs: ".join(", ",@defaultSystemExcl,@{$config{'system-dir'}})."\n");
# If we excluding data too...
if ($config{'exclude-data'}) {
printLog("Exclude Data Dirs: ".join(", ",@defaultDataExcl,@{$config{'data-dir'}})."\n");
printLog(LOG_NOTICE,"Exclude Data Dirs: ".join(", ",@defaultDataExcl,@{$config{'data-dir'}})."\n");
}
}
printLog("Exclude Files: ".join(", ",@{$config{'exclude-file'}})."\n");
printLog(LOG_NOTICE,"Exclude Files: ".join(", ",@{$config{'exclude-file'}})."\n");
# We need an entry for our main dir before we start
$doBackup{""} = 0;
......@@ -803,7 +819,7 @@ sub backup
);
printLog("Processing stale directories...\n");
printLog(LOG_INFO,"Processing stale directories...\n");
my @rmlist;
# Total item by item
find (
......@@ -815,20 +831,18 @@ sub backup
(my $path = $File::Find::dir) =~ s#^$dest/?##;
# Does this dir exist on the backup, but not on the fileserver?
if (!defined($srcFileList{$path})) {
printLog("Remove path '[$dest]/$path'\n");
push(@rmlist,"$dest/$path");
push(@rmlist,$path);
}
},
},
$dest
);
printLog("Removing paths...\n");
foreach my $rmitem ( @rmlist ) {
rmtree($rmitem);
printLog(LOG_DEBUG,"Remove path '[$dest]/$rmitem'\n");
rmtree("$dest/$rmitem");
}
printLog("BACKUP END\n");
printLog(LOG_NOTICE,"BACKUP END\n");
}
......@@ -869,7 +883,7 @@ sub restore
# Check if we have all our source files
if ( ! -f "$source/$path/.dbackup-state" ) {
printLog("S: Path '[$source]/($path)' is MISSING .dbackup-state\n");
printLog(LOG_WARNING,"S: Path '[$source]/($path)' is MISSING .dbackup-state\n");
return @list;
}
......@@ -878,7 +892,7 @@ sub restore
# Check we have at least the version attribute
if (!defined($origPathAttribs{$path}) || !defined($origPathAttribs{$path}->{'dbackup.version'})) {
print(STDERR "ERROR: No dbackup version information found in '$source/$path/.dbackup-state', IGNORING\n");
printLog(LOG_ERROR, "No dbackup version information found in '$source/$path/.dbackup-state', IGNORING\n");
delete($origDirList{$path});
delete($origFileList{$path});
return @list;
......@@ -887,7 +901,7 @@ sub restore
# During our check, we need to create the dir, we may not have a backup file
# so we do it here.
if ( ! -d "$dest/$path") {
printLog("R: Path '[$dest]/($path)' creating directory\n");
printLog(LOG_INFO,"R: Path '[$dest]/($path)' creating directory\n");
mkpath("$dest/$path");
}
......@@ -898,7 +912,7 @@ sub restore
# Loop through backup sequences
for (my $seq = 0; $seq <= $origPathAttribs{$path}->{'sequence'}; $seq++) {
printLog("R: Path '[$dest]/$path' restoring files ".($seq+1)." of ".
printLog(LOG_DEBUG,"R: Path '[$dest]/$path' restoring files ".($seq+1)." of ".
($origPathAttribs{$path}->{'sequence'}+1)."\n");
# Args for tar
......@@ -926,9 +940,7 @@ sub restore
-f "$source/$path/dbackup$seq.manifest" ||
-f "$source/$path/dbackup$seq.snar" ) && $seq > 0
) {
# NK: Maybe add this to debug log?
#printLog("S: Path '[$source]/($path)' IGNORING DUE TO NO BACKUP FILE\n");
print(STDERR "ERROR: Backup file '$source/$path/dbackup$seq.tar$tarExt' not found\n");
printLog(LOG_WARNING,"Backup file '$source/$path/dbackup$seq.tar$tarExt' not found, IGNORING\n");
}
return @list;
......@@ -936,11 +948,11 @@ sub restore
# Check we have files we need/created
if ( ! -f "$source/$path/dbackup$seq.index" ) {
print(STDERR "ERROR: Manifest file '$source/$path/dbackup$seq.index' not found\n");
printLog(LOG_WARNING,"Manifest file '$source/$path/dbackup$seq.index' not found\n");
return @list;
}
if ( ! -f "$source/$path/dbackup$seq.manifest" ) {
print(STDERR "ERROR: Manifest file '$source/$path/dbackup$seq.manifest' not found\n");
printLog(LOG_WARNING,"Manifest file '$source/$path/dbackup$seq.manifest' not found\n");
return @list;
}
......@@ -971,16 +983,16 @@ sub restore
@tarArgs
);
if ($? == -1) {
printLog(" - Failed to execute: $!\n");
printLog(LOG_ERROR,"Failed to execute: $!\n");
exit 1;
} elsif ($? & 127) {
printLog(" - Child died with signal %d\n",($? & 127));
printLog(LOG_ERROR,"Child died with signal %d\n",($? & 127));
exit 1;
} else {
my $retcode = $? >> 8;
# If tar died, lets die too
if ($retcode == 2) {
print(STDERR "ERROR: tar died with error code $retcode\n");
printLog(LOG_ERROR,"tar died with error code $retcode\n");
exit 1;
}
}
......@@ -1007,7 +1019,7 @@ sub restore
# Strip first part of the path
(my $path = $File::Find::dir) =~ s#^$source/?##;
printLog("R: Path '[$dest]/$path' restoring attributes\n");
printLog(LOG_DEBUG,"R: Path '[$dest]/$path' restoring attributes\n");
# Loop with directories in this path
foreach my $dname (keys %{$origDirList{$path}}) {
......@@ -1019,13 +1031,13 @@ sub restore
# Restore attribs
if (!chown($dir->{'uid'},$dir->{'gid'},$fdirname)) {
print(STDERR "ERROR: Failed to chown(".$dir->{'uid'}.",".$dir->{'gid'}.") '$fdirname': $!\n");
printLog(LOG_ERROR,"Failed to chown(".$dir->{'uid'}.",".$dir->{'gid'}.") '$fdirname': $!\n");
}
if (!chmod($dir->{'mode'},$fdirname)) {
print(STDERR "ERROR: Failed to chmod(".$dir->{'mode'}.") '$fdirname': $!\n");
printLog(LOG_ERROR,"Failed to chmod(".$dir->{'mode'}.") '$fdirname': $!\n");
}
if (!utime($dir->{'atime'},$dir->{'mtime'},$fdirname)) {
print(STDERR "ERROR: Failed to utime(".$dir->{'atime'}.",".$dir->{'mtime'}.") '$fdirname': $!\n");
printLog(LOG_ERROR,"Failed to utime(".$dir->{'atime'}.",".$dir->{'mtime'}.") '$fdirname': $!\n");
}
}
......@@ -1039,18 +1051,18 @@ sub restore
# Restore attribs
if (!chown($file->{'uid'},$file->{'gid'},$ffilename)) {
print(STDERR "ERROR: Failed to chown(".$file->{'uid'}.",".$file->{'gid'}.") '$ffilename': $!\n");
printLog(LOG_ERROR,"Failed to chown(".$file->{'uid'}.",".$file->{'gid'}.") '$ffilename': $!\n");
}
if (!chmod($file->{'mode'},$ffilename)) {
print(STDERR "ERROR: Failed to chmod(".$file->{'mode'}.") '$ffilename': $!\n");
printLog(LOG_ERROR,"Failed to chmod(".$file->{'mode'}.") '$ffilename': $!\n");
}
if (!utime($file->{'atime'},$file->{'mtime'},$ffilename)) {
print(STDERR "ERROR: Failed to utime(".$file->{'atime'}.",".$file->{'mtime'}.") '$ffilename': $!\n");
printLog(LOG_ERROR,"Failed to utime(".$file->{'atime'}.",".$file->{'mtime'}.") '$ffilename': $!\n");
}
}
}
printLog("RESTORE START: $source => $dest\n");
printLog(LOG_NOTICE,"RESTORE START: $source => $dest\n");
# This basically does our backup for us...
find (
......@@ -1062,15 +1074,33 @@ sub restore
$source
);
printLog("RESTORE END\n");
printLog(LOG_NOTICE,"RESTORE END\n");
}
# Display log line
sub printLog {
my $msg = shift;
my ($level,$msg,@args) = @_;
# Work out level txt all nicely
my $levelTxt = "UNKNOWN";
if ($level == LOG_DEBUG) {
$levelTxt = "DEBUG";
} elsif ($level == LOG_INFO) {
$levelTxt = "INFO";
} elsif ($level == LOG_NOTICE) {
$levelTxt = "NOTICE";
} elsif ($level == LOG_WARNING) {
$levelTxt = "WARNING";
} elsif ($level == LOG_DEBUG) {
$levelTxt = "DEBUG";
}
printf(STDERR "%s: %s", strftime('%F %T',localtime()), $msg);
# Check log level
if ($level >= $config{'log-level'}) {
printf(STDERR "%s/$levelTxt: %s", strftime('%F %T',localtime()), $msg, @args);
}
}
......@@ -1087,6 +1117,8 @@ Usage: $0 [args] <src> <dst>
General Options:
--help What you seeing now.
--config=file Config file to use.
--log-level 1 = debug, 2 = info, 3 = notice
4 = warning, 5 = debug
Backing Options:
--backup|-b Backup src to dst.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment