]> wagner.pp.ru Git - oss/restore.git/commitdiff
Added backup script
authorVictor Wagner <vitus@wagner.pp.ru>
Fri, 7 Apr 2023 08:05:07 +0000 (11:05 +0300)
committerVictor Wagner <vitus@wagner.pp.ru>
Fri, 7 Apr 2023 08:05:07 +0000 (11:05 +0300)
aftermount [new file with mode: 0755]
backup [new file with mode: 0755]
backup.sudo [new file with mode: 0644]

diff --git a/aftermount b/aftermount
new file mode 100755 (executable)
index 0000000..fe22565
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/bash
+#
+# Intended to be called from file manager as aftermount command.
+# Checks if mounted volume looks like rsnapshot snapshot_root and if
+# so, asks to run backup in a graphical dialog.
+#
+# Expected backup script installed into BACKUP path below and
+# passwordless sudo available for it for any user of %plugdev group
+
+BACKUP=/usr/local/sbin/backup
+SUDOCMD=sudo
+spacefm_dialog() {
+       eval "$(spacefm -g --title "$1" --label "$2" --button no --button yes)"
+       [ "$dialog_pressed_label" = "yes" ]&& return 0
+       return 1
+}
+
+spacefm_monolog() {
+       spacefm -g --title "$1" --label "$2" --window-icon "$3" --button ok >/dev/null
+}
+
+zenity_dialog() {
+       zenity --question --title "$1" --text "$2"
+}
+
+zenity_monolog() {
+       zenity --$3 --title "$1" --text "$2"
+}
+mountpoint="$1"
+grep -q "^snapshot_root        $mountpoint" /etc/rsnapshot.conf || exit 0
+
+
+
+eval "$(df -H "$mountpoint"|awk 'NR>1 {printf "dev=%s\nsize=%s\nfree=%s\nmp=%s",$1,$2,$4,$6;}')"
+message="Backup media inserted into $dev\nTotal space $size\nFree space=$free\n. Would you like to start backup?"
+
+if command -v spacefm; then
+       iface=spacefm
+else
+       iface=zenity
+fi
+
+${iface}_dialog "Backup media inserted" "$message" || exit 0
+
+if sudo $BACKUP; then
+       ${iface}_monolog "Backup successful" "Backup finished successfully" info
+else 
+       ${iface}_monolog "Backup failed" "Backup finished with errors. See logs" error
+       exit 1
+fi
diff --git a/backup b/backup
new file mode 100755 (executable)
index 0000000..96467fe
--- /dev/null
+++ b/backup
@@ -0,0 +1,115 @@
+#!/usr/bin/perl
+# If we have rsnapshot, we have perl to run it
+
+=head1 NAME
+
+backup - manages multilevel rsnapshot backups
+
+=head1 SYNOPSIS
+
+    backup
+
+=head1 DESCRIPTION
+
+This script is intended to make B<rsnapshot>(1) backups to removable
+devices, which are performed by hand and with some irregularity.
+
+It reads C</etc/rsnapshot.conf> and finds out snapshot root and
+list of backup levels.
+
+It expected that removable device is automounted.
+
+It checks existing backups in the C<$snapshot_root>, and if oldest snapshot
+of level n is newer that next level was done (as determined by
+modification date of C<$snapshot_root/$level-stamp>) next level is
+performed.
+
+If all backups were successful, unmounts all partitions of device where
+C<$snapshot_root> is located.
+
+=head1 FILES
+
+/etc/rsnapshot.conf
+
+=head1 AUTHOR
+
+Victor Wagner <vitus@wagner.pp.ru>
+
+=cut
+
+# Read rsnapshot conf, find out snapshot_root and retain.
+open $conf, "<","/etc/rsnapshot.conf" or die "/etc/rsnapshot.conf:$!\n";
+my @levels=();
+my $snapshot_root=undef;
+LINE:
+while (<$conf>) {
+       if (/^snapshot_root\t+(.*)$/) {
+               $snapshot_root= $1;
+               next LINE;
+       }       
+       if (/^retain\s+(\w+)\s+(\d+)/) {
+               my $level = $1;
+               my $number = $2;
+               if (@levels) {
+                       push @{$levels[$#levels]},$level;
+               }
+               push @levels,[$level,$number];
+       }
+}
+# last level is incomplete, we don't need it.
+pop @levels;
+
+die "No backup media mounted on $snapshot_root\n" unless -d $snapshot_root;
+# Now we have following triples:
+# "level,number,nextlevel"
+my $level;
+LEVEL:
+while (@levels) {
+       $triple = pop @levels;
+       $level=$triple->[0];
+       my $number=$triple->[1] -1;
+       my $nextlevel=$triple->[2];
+       if (! -d "$snapshot_root/$level.$number") {
+           #not enough retained backups of on this level
+               next LEVEL;
+       }
+       if (-f "$snapshot_root/${nextlevel}-stamp" &&
+               -M "$snapshot_root/${nextlevel}-stamp" < 
+               -M "$snapshot_root/$level.$number") {
+               # last backup on level nextlevel happen after oldest retanined
+               # on level level
+               next LEVEL;
+       }
+    run_rsnapshot($nextlevel);
+       # touch stamp file
+       open my $stamp, ">+","$snapshot_root/${nextlevel}-stamp";
+       close $stamp;
+}
+run_rsnapshot($level); 
+# Размонтируем файловую систему, содержащую snapshot_root
+my @lines = `df $snapshot_root`;
+my @line = split(/\s+/,pop @lines);
+my $device = shift @line;
+$device =~ s/\d$//; # remove partition number 
+open my $mount,"mount|" or die "Cannot execute mount:$!";
+my @to_umount=();
+while (<$mount>) {
+       if (m!^($device\d) on !) {
+               push @to_umount,$1;
+       }
+}
+close $mount;
+for $device (@to_umount) {
+    print STDERR  "umount $device\n";
+       system("umount",$device);
+}
+
+sub run_rsnapshot {
+    my $level = shift;
+    print STDERR "running rsnapshot $level\n";
+    my $status= system("rsnapshot",$level) >> 8;
+    if ($status) { 
+        print STDERR "rnsapshot $level finished with code $status\n";
+        exit $status;
+    }
+}
diff --git a/backup.sudo b/backup.sudo
new file mode 100644 (file)
index 0000000..81b42b6
--- /dev/null
@@ -0,0 +1 @@
+%plugdev       ALL=(ALL) NOPASSWD: /usr/local/sbin/backup