#!/usr/bin/perl
################################################################################
#
# Perl implementation of rsync-backup.sh
#
################################################################################
use Mojo::Base -strict;
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
use File::Basename;
my $program_name = basename($0,q{.pl});
##############################################################################################
#
# Rarely changed system configuration variables
#
# Backup volumnes, sources, and exclusions are defined in a config file # $DRIVES_CONF
# Note: for sources and exclusions in config, bin lib lib64 and sbin are symlinks to /usr
#
##############################################################################################
my $DRIVES_CONF = q{/root/etc/rsync-backup/drives.conf};
my $FS_MOUNTPOINT = q{/mnt};
my $LOG_DIR = q{/root/log};
my $VERBOSE = q{-v};
#
# Init logging
#
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init( { level => $DEBUG, file => ">>$LOG_DIR/$program_name.log"},
{ level => $DEBUG, file => "STDOUT" } );
INFO("$0 - Begin Program");
#
# Load Drives config
#
my $backup_vols = do($DRIVES_CONF);
die "Error parsing config file: $@" if $@;
die "Error reading config file: $!" unless defined $backup_vols;
TRACE(Dumper $backup_vols);
#
# Setup Commands
#
my $cmds = setup_commands();
TRACE(Dumper $cmds);
################################################################################
#
# Step 1: Let's find out what backup volume ( if any ) is mounted.
#
################################################################################
# Initialize Target variables
my $T_UUID;
my $T_FSTYPE;
my $T_LABEL;
# Loop through lsblk
foreach my $line ( qx{ $cmds->{'lsblk'}->{'cmd'} } ) {
# while we don't have a T_UUID
if ( not $T_UUID ) {
# Extract data from lsblk row
my ($UUID) = split(/\s+/,$line);
# if we match one of the UUIDs on our list
if ( grep (/$UUID/, sort keys %{$backup_vols}) ) {
# save off the device information
($T_UUID, $T_FSTYPE, $T_LABEL ) = split(/\s+/,$line);
}; # if grep
}; # if not T_UUID
} # foreach $line
# Check to make sure we have a device attached
if ( not $T_UUID ) {
FATAL("Fatal Error: Could not find a drive to use.");
FATAL qx{ $cmds->{'lsblk'}->{'cmd'} };
FATAL "$0 - End Program";
exit 1;
}
INFO "Target Volume: $T_UUID, $T_FSTYPE, $T_LABEL";
################################################################################
#
# We now have the $T_UUID, $T_FSTYPE, $T_LABEL
# so we're ready to construct the rest of the commands and options
#
# mount->cmd needs T_FSTYPE and T_UUID
# rsync-opt needs excludes filename, derived from T_UUID
#
################################################################################
$cmds->{'mount'}->{'cmd'} = $cmds->{'mount'}->{'bin'} . qq{ $VERBOSE -t $T_FSTYPE -U $T_UUID $FS_MOUNTPOINT } . $cmds->{'mount'}->{'opt'};
# force checksums = -c
$cmds->{'rsync'}->{'opt'} = qq{-a $VERBOSE --delete --delete-excluded --delete-before --exclude-from=$backup_vols->{$T_UUID}->{'EXCLUDES'} };
$cmds->{'rsync'}->{'cmd'} = qq{$cmds->{'ionice'}->{'bin'} $cmds->{'ionice'}->{'opt'} }
. qq{$cmds->{'rsync'}->{'bin'} $cmds->{'rsync'}->{'opt'} }
. qq{$backup_vols->{$T_UUID}->{'SOURCES'} $FS_MOUNTPOINT};
TRACE(Dumper $cmds);
##############################################################################################
#
# Begin
#
##############################################################################################
INFO "Beginning rsync backup of data to portable drive.";
INFO "--------------------------------------------------------------------------------";
INFO " Backup up directories: $backup_vols->{$T_UUID}->{'SOURCES'}";
INFO " to: $FS_MOUNTPOINT";
INFO " with rsync options: $cmds->{'rsync'}->{'opt'}";
INFO "---- Mounting Portable Drive ---";
my $rtn_code = execute_cmd ( $cmds->{'mount'}->{'cmd'} );
if ( $rtn_code == 0 ) {
INFO "---- Beginning Sync Operation ---";
execute_cmd ( $cmds->{'rsync'}->{'cmd'} );
};
INFO "---- Unmounting Portable Drive ---";
execute_cmd ( $cmds->{'umount'}->{'cmd'} );
INFO("$0 - End Program");
exit 0;
##############################################################################################
#
# Subroutine: setup_commands()
#
##############################################################################################
sub setup_commands {
my $c;
# lsblk
my $retval = qx{ which lsblk };
chomp $retval;
$c->{'lsblk'}->{'bin'} = $retval;
$c->{'lsblk'}->{'opt'} = q{-bnp -o UUID,FSTYPE,LABEL};
$c->{'lsblk'}->{'cmd'} = qq{$c->{'lsblk'}->{'bin'} $c->{'lsblk'}->{'opt'}};
# mount
$retval = qx{ which mount };
chomp $retval;
$c->{'mount'}->{'bin'} = $retval;
$c->{'mount'}->{'opt'} = qq{-o context="system_u:object_r:removable_t:s0"};
# cmd needs $T_FSTYPE and $T_UUID, defer undtil drive selected
# umount
$retval = qx{ which umount };
chomp $retval;
$c->{'umount'}->{'bin'} = $retval;
$c->{'umount'}->{'opt'} = $VERBOSE;
$c->{'umount'}->{'cmd'} = qq{$c->{'umount'}->{'bin'} $c->{'umount'}->{'opt'} $FS_MOUNTPOINT};
# ionice
$retval = qx{ which ionice };
chomp $retval;
$c->{'ionice'}->{'bin'} = $retval;
$c->{'ionice'}->{'opt'} = qq{-c 3};
$c->{'ionice'}->{'cmd'} = qq{$c->{'ionice'}->{'bin'} $c->{'ionice'}->{'opt'}};
# rsync
$retval = qx{ which rsync };
chomp $retval;
$c->{'rsync'}->{'bin'} = $retval;
# rsync->opt needs $backup_vols, defer
# rsync-cmd needs rsync-opt, defer
return $c;
}; # sub setup_commands
##############################################################################################
#
# Subroutine: execute_cmd( qq{ some command text $variable } );
#
##############################################################################################
sub execute_cmd {
my $cmd = shift;
INFO " Execute Command='$cmd'";
DEBUG "---- Command Output ----";
open(STATUS, "$cmd 2>&1 |") or die "can't fork: $!";
while (my $line = <STATUS>) {
DEBUG $line;
}
close STATUS or die "bad $cmd $! $?";
DEBUG "CHILD_ERROR_NATIVE=${^CHILD_ERROR_NATIVE}";
DEBUG "--------------------------";
return ${^CHILD_ERROR_NATIVE};
}; # sub execute_cmd
##############################################################################################
__END__
##############################################################################################
=pod
=head1 Old error handling
###############################################
# Subroutine sad_trombone (signifies failure)
###############################################
sad_trombone () {
umount $FS_MOUNTPOINT;
# umount $MNT_LAURIE_C;
exit;
}
=head1 Old automation instrucations
Sticking:
rsync-backup.sh >> logfile.txt 2>&1
into your crontab should take care of this. As long as everything's hooked up.
There is NO error checking beyond rudimentary checks for the presence of a backup drive.
=head1 Sample Output from lsblk
[root@orion bin]# lsblk -bnp -o KNAME,MAJ:MIN,SIZE,UUID,FSTYPE,LABEL
/dev/sda 8:0 1000204886016
/dev/sda1 8:1 524288000 a33dd657-0219-45ac-b972-b2776d544119 ext4
/dev/sda2 8:2 999678803968 P4Igma-nf61-96np-EDMc-Grio-BUIL-j12JgR LVM2_member
/dev/dm-0 253:0 53687091200 e4a64529-37ca-4006-917b-b480e98886cc ext4
/dev/dm-1 253:1 4227858432 faa6b4f4-1697-409e-be8a-aea4e31f028b swap
/dev/dm-2 253:2 679615660032 7ef0fc8b-f444-4e68-b54b-5e38eff7ed84 ext4
/dev/dm-3 253:3 262144000000 7629eb3d-7fb2-46f1-8d9a-244fd3960fb7 ext4
/dev/sdb 8:16 1000204886016
/dev/sdb1 8:17 1000203837440 6720f72b-86ad-4568-b8dc-b22f69cf2923 btrfs backup02
/dev/sr0 11:0 1073741312
=cut
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎