mikelieman

Backing up with rsync. (Perl)

Oct 24th, 2020 (edited)
1,524
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/perl
  2.  
  3. ################################################################################
  4. #
  5. # Perl implementation of rsync-backup.sh
  6. #
  7. ################################################################################
  8.  
  9. use Mojo::Base -strict;
  10. use Data::Dumper;
  11. $Data::Dumper::Sortkeys = 1;
  12.  
  13. use File::Basename;
  14. my $program_name = basename($0,q{.pl});
  15.  
  16. ##############################################################################################
  17. #
  18. #  Rarely changed system configuration variables
  19. #
  20. #  Backup volumnes, sources, and exclusions are defined in a config file # $DRIVES_CONF
  21. #  Note: for sources and exclusions in config, bin lib lib64 and sbin are symlinks to /usr
  22. #
  23. ##############################################################################################
  24. my $DRIVES_CONF = q{/root/etc/rsync-backup/drives.conf};
  25. my $FS_MOUNTPOINT = q{/mnt};
  26. my $LOG_DIR = q{/root/log};
  27. my $VERBOSE = q{-v};
  28.  
  29.  
  30. #
  31. # Init logging
  32. #
  33. use Log::Log4perl qw(:easy);
  34. Log::Log4perl->easy_init(   {   level => $DEBUG, file  => ">>$LOG_DIR/$program_name.log"},
  35.                             {   level => $DEBUG, file  => "STDOUT"  }   );
  36.  
  37. INFO("$0 - Begin Program");
  38.  
  39. #
  40. # Load Drives config
  41. #
  42. my $backup_vols = do($DRIVES_CONF);
  43. die "Error parsing config file: $@" if $@;
  44. die "Error reading config file: $!" unless defined $backup_vols;
  45.  
  46. TRACE(Dumper $backup_vols);
  47.  
  48. #
  49. # Setup Commands
  50. #
  51. my $cmds = setup_commands();
  52.  
  53. TRACE(Dumper $cmds);
  54.  
  55. ################################################################################
  56. #
  57. # Step 1:  Let's find out what backup volume ( if any ) is mounted.
  58. #
  59. ################################################################################
  60.  
  61. #  Initialize Target variables
  62. my $T_UUID;
  63. my $T_FSTYPE;
  64. my $T_LABEL;
  65.  
  66. #  Loop through lsblk
  67. foreach my $line ( qx{ $cmds->{'lsblk'}->{'cmd'} } ) {
  68.  
  69.     #  while we don't have a T_UUID
  70.     if ( not $T_UUID ) {
  71.  
  72.         #  Extract data from lsblk row
  73.         my ($UUID) = split(/\s+/,$line);
  74.  
  75.         # if we match one of the UUIDs on our list
  76.         if ( grep (/$UUID/, sort keys %{$backup_vols}) ) {  
  77.  
  78.             #  save off the device information
  79.             ($T_UUID, $T_FSTYPE, $T_LABEL ) = split(/\s+/,$line);
  80.  
  81.         };  # if grep
  82.  
  83.     }; # if not T_UUID
  84.  
  85. } # foreach $line
  86.  
  87.  
  88. #  Check to make sure we have a device attached
  89. if ( not $T_UUID ) {
  90.     FATAL("Fatal Error:  Could not find a drive to use.");
  91.     FATAL qx{ $cmds->{'lsblk'}->{'cmd'} };
  92.     FATAL "$0 - End Program";
  93.     exit 1;
  94. }
  95.  
  96. INFO "Target Volume: $T_UUID, $T_FSTYPE, $T_LABEL";
  97.  
  98. ################################################################################
  99. #
  100. # We now have the $T_UUID, $T_FSTYPE, $T_LABEL
  101. # so we're ready to construct the rest of the commands and options
  102. #
  103. # mount->cmd needs T_FSTYPE and T_UUID
  104. # rsync-opt needs excludes filename, derived from T_UUID
  105. #
  106. ################################################################################
  107.  
  108. $cmds->{'mount'}->{'cmd'} = $cmds->{'mount'}->{'bin'} . qq{ $VERBOSE -t $T_FSTYPE -U $T_UUID $FS_MOUNTPOINT } . $cmds->{'mount'}->{'opt'};
  109.  
  110. # force checksums = -c
  111. $cmds->{'rsync'}->{'opt'} = qq{-a $VERBOSE --delete --delete-excluded --delete-before --exclude-from=$backup_vols->{$T_UUID}->{'EXCLUDES'} };
  112.  
  113. $cmds->{'rsync'}->{'cmd'}   = qq{$cmds->{'ionice'}->{'bin'} $cmds->{'ionice'}->{'opt'} }
  114.                             . qq{$cmds->{'rsync'}->{'bin'} $cmds->{'rsync'}->{'opt'} }
  115.                             . qq{$backup_vols->{$T_UUID}->{'SOURCES'} $FS_MOUNTPOINT};
  116.  
  117. TRACE(Dumper $cmds);
  118.  
  119. ##############################################################################################
  120. #
  121. #  Begin
  122. #
  123. ##############################################################################################
  124.  
  125. INFO "Beginning rsync backup of data to portable drive.";
  126. INFO "--------------------------------------------------------------------------------";
  127. INFO "    Backup up directories: $backup_vols->{$T_UUID}->{'SOURCES'}";
  128. INFO "    to: $FS_MOUNTPOINT";
  129. INFO "    with rsync options: $cmds->{'rsync'}->{'opt'}";
  130.  
  131. INFO "----  Mounting Portable Drive  ---";
  132. my $rtn_code = execute_cmd ( $cmds->{'mount'}->{'cmd'} );
  133.  
  134. if ( $rtn_code == 0 ) {
  135.     INFO "----  Beginning Sync Operation  ---";
  136.     execute_cmd ( $cmds->{'rsync'}->{'cmd'} );
  137. };
  138.  
  139. INFO "----  Unmounting Portable Drive  ---";
  140.     execute_cmd ( $cmds->{'umount'}->{'cmd'} );
  141.  
  142. INFO("$0 - End Program");
  143. exit 0;
  144.  
  145. ##############################################################################################
  146. #
  147. # Subroutine: setup_commands()
  148. #
  149. ##############################################################################################
  150. sub setup_commands {
  151.  
  152.     my $c;
  153.  
  154.     # lsblk
  155.     my $retval = qx{ which lsblk };
  156.     chomp $retval;
  157.     $c->{'lsblk'}->{'bin'} = $retval;
  158.     $c->{'lsblk'}->{'opt'} = q{-bnp -o UUID,FSTYPE,LABEL};
  159.     $c->{'lsblk'}->{'cmd'} = qq{$c->{'lsblk'}->{'bin'} $c->{'lsblk'}->{'opt'}};
  160.  
  161.     # mount
  162.     $retval = qx{ which mount };
  163.     chomp $retval;
  164.     $c->{'mount'}->{'bin'} = $retval;
  165.     $c->{'mount'}->{'opt'} = qq{-o context="system_u:object_r:removable_t:s0"};
  166.     # cmd needs $T_FSTYPE and $T_UUID, defer undtil drive selected
  167.  
  168.     # umount
  169.     $retval = qx{ which umount };
  170.     chomp $retval;
  171.     $c->{'umount'}->{'bin'} = $retval;
  172.     $c->{'umount'}->{'opt'} = $VERBOSE;
  173.     $c->{'umount'}->{'cmd'} = qq{$c->{'umount'}->{'bin'} $c->{'umount'}->{'opt'} $FS_MOUNTPOINT};
  174.  
  175.     # ionice
  176.     $retval = qx{ which ionice };
  177.     chomp $retval;
  178.     $c->{'ionice'}->{'bin'} = $retval;
  179.     $c->{'ionice'}->{'opt'} = qq{-c 3};
  180.     $c->{'ionice'}->{'cmd'} = qq{$c->{'ionice'}->{'bin'} $c->{'ionice'}->{'opt'}};
  181.  
  182.     # rsync
  183.     $retval = qx{ which rsync };
  184.     chomp $retval;
  185.     $c->{'rsync'}->{'bin'} = $retval;
  186.     # rsync->opt needs $backup_vols, defer
  187.     # rsync-cmd needs rsync-opt, defer
  188.    
  189.     return $c;
  190.  
  191. }; # sub setup_commands
  192.  
  193. ##############################################################################################
  194. #
  195. # Subroutine: execute_cmd( qq{ some command text $variable } );
  196. #
  197. ##############################################################################################
  198. sub execute_cmd {
  199.  
  200.     my $cmd = shift;
  201.     INFO "    Execute Command='$cmd'";
  202.  
  203.     DEBUG "----  Command Output  ----";
  204.     open(STATUS, "$cmd 2>&1 |") or die "can't fork: $!";
  205.  
  206.     while (my $line = <STATUS>) {
  207.         DEBUG $line;
  208.     }
  209.  
  210.     close STATUS or die "bad $cmd $! $?";
  211.  
  212.     DEBUG "CHILD_ERROR_NATIVE=${^CHILD_ERROR_NATIVE}";
  213.  
  214.     DEBUG "--------------------------";
  215.  
  216.     return ${^CHILD_ERROR_NATIVE};
  217.  
  218. }; # sub execute_cmd
  219.  
  220. ##############################################################################################
  221. __END__
  222. ##############################################################################################
  223.  
  224. =pod
  225.  
  226. =head1 Old error handling
  227.  
  228.     ###############################################
  229.     # Subroutine sad_trombone (signifies failure)
  230.     ###############################################
  231.     sad_trombone () {
  232.         umount $FS_MOUNTPOINT;
  233.     #   umount $MNT_LAURIE_C;
  234.         exit;
  235.     }
  236.  
  237. =head1 Old automation instrucations
  238.  
  239.     Sticking:
  240.  
  241.         rsync-backup.sh >> logfile.txt 2>&1
  242.  
  243.     into your crontab should take care of this.  As long as everything's hooked up.  
  244.     There is NO error checking beyond rudimentary checks for the presence of a backup drive.
  245.  
  246. =head1 Sample Output from lsblk
  247.  
  248.  [root@orion bin]# lsblk -bnp -o KNAME,MAJ:MIN,SIZE,UUID,FSTYPE,LABEL
  249.  /dev/sda    8:0   1000204886016                                                    
  250.  /dev/sda1   8:1       524288000 a33dd657-0219-45ac-b972-b2776d544119   ext4        
  251.  /dev/sda2   8:2    999678803968 P4Igma-nf61-96np-EDMc-Grio-BUIL-j12JgR LVM2_member
  252.  /dev/dm-0 253:0     53687091200 e4a64529-37ca-4006-917b-b480e98886cc   ext4        
  253.  /dev/dm-1 253:1      4227858432 faa6b4f4-1697-409e-be8a-aea4e31f028b   swap        
  254.  /dev/dm-2 253:2    679615660032 7ef0fc8b-f444-4e68-b54b-5e38eff7ed84   ext4        
  255.  /dev/dm-3 253:3    262144000000 7629eb3d-7fb2-46f1-8d9a-244fd3960fb7   ext4        
  256.  /dev/sdb    8:16  1000204886016                                                    
  257.  /dev/sdb1   8:17  1000203837440 6720f72b-86ad-4568-b8dc-b22f69cf2923   btrfs       backup02
  258.  /dev/sr0   11:0      1073741312                                                    
  259.  
  260. =cut
  261.  
RAW Paste Data