From: Victor Wagner Date: Fri, 7 Apr 2023 08:05:07 +0000 (+0300) Subject: Added backup script X-Git-Url: http://wagner.pp.ru/gitweb/?a=commitdiff_plain;h=df07d26b9c2952ff55689ecbe32d8abe2f88541c;p=oss%2Frestore.git Added backup script --- diff --git a/aftermount b/aftermount new file mode 100755 index 0000000..fe22565 --- /dev/null +++ b/aftermount @@ -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 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(1) backups to removable +devices, which are performed by hand and with some irregularity. + +It reads C 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 + +=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 index 0000000..81b42b6 --- /dev/null +++ b/backup.sudo @@ -0,0 +1 @@ +%plugdev ALL=(ALL) NOPASSWD: /usr/local/sbin/backup