User Tools

Site Tools


efficient_backups_with_rsnapshot

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
efficient_backups_with_rsnapshot [2009/12/02 07:08]
tkbletsc Page name changed from quick_backup_from_windows_with_cygwin_rsync_to_linux to efficient_backups_with_rsnapshot
efficient_backups_with_rsnapshot [2010/07/12 06:04] (current)
tkbletsc
Line 1: Line 1:
-====== ​Quick backup from Windows ​with cygwin/​rsync to Linux ======+====== ​Efficient backups ​with rsnapshot ​======
  
-  * Install cygwin with rsync and ssh +Basically, do this: http://troy.jdmz.net/rsnapshot/
-  * Set up SSH keys +
-  * Associate ​.sh files with cygwin/bin/bash in Windows +
-  * Make a script like this:+
  
-<​code>​ +Reminder: on debian/ubuntu, you need to "sudo apt-get install liblchown-perl"​ so rsnapshot can set symlink ownership.
-#!/bin/sh+
  
-date +"​=== ​%Y-%m-%d %H:%M:%S Start ===" ​>> ​/g/Programs/​log.txt +In place of his rickety ''​validate-rsync''​ script, use this ''​rrsync''​ script on clients: 
-rsync -auzv --delete ​/c/Documents doc:private2>&1 >> ​/g/Programs/log.txt +<code perl> 
-date +"​=== ​%Y-%m-%d %H:%M:%S Done  ​==="​ >> /g/Programs/log.txt+#​!/​usr/​bin/​perl 
 +# Name: /​usr/​local/​bin/​rrsync (should have a symlink in /usr/bin) 
 +# Purpose: Restricts rsync to subdirectory declared in .ssh/​authorized_keys 
 +
 +# The client uses "rsync -av -e ssh src/ server:​dir/",​ and sshd on the server 
 +# executes this program when .ssh/​authorized_keys has '​command="​..."'​. 
 +#       For example: 
 +# command="​rrsync logs/​client"​ ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAzGhEeNlPr... 
 +# command="​rrsync ​-ro results"​ ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAmkHG1WCjC... 
 +#   The former limits the remote client to a specific subdirectory of "​logs"​ 
 +#   and the latter allows read-only access to a different dirctory. 
 + 
 +use Socket; 
 +use constant LOGFILE => '/​home/​tkbletsc/​rrsync.log';​ 
 +my $Usage = <<​EOM;​ 
 +Use '​command="​$0 [-ro] subdir"'​ 
 +        in front of lines in $ENV{HOME}/​.ssh/​authorized_keys 
 +EOM 
 + 
 +# Format of the envrionment variables set by sshd: 
 +# SSH_ORIGINAL_COMMAND=rsync --server ​         -vlogDtpr --partial . dir # push 
 +# SSH_ORIGINAL_COMMAND=rsync --server --sender -vlogDtpr --partial . dir # pull 
 +# SSH_CLIENT=client_addr client_port server_port 
 + 
 +my $ro = (@ARGV and $ARGV[0] eq '​-ro'​) ? shift ''; ​   # -ro Read-Only 
 +my $top1 shift; 
 +die "No subdirectory specified\n$Usage"​ unless defined $top1; 
 +my $top2 = "$top1/"; 
 + 
 +my $command = $ENV{SSH_ORIGINAL_COMMAND};​ 
 +die "Not invoked via sshd\n$Usage" ​     unless defined $command; 
 + 
 +my ($cmd,​$requested_target) = $command =~ /(.* \.) ?(.*)/; 
 +die "​SSH_ORIGINAL_COMMAND='​$command'​ is not rsync\n" unless $cmd =~ /​^rsync\s/;​ 
 +die "​$0 ​-ro: sending to read-only directory $requested_target not allowed\n"​ 
 +        if $ro and $cmd !~ /​^rsync ​--server --sender ​/
 + 
 +my $dir = $requested_target;​ 
 +$dir =~ tr|-~\\ _/a-zA-Z0-9.,:@|_|c; ​   # Don't allow ;|][}{*? 
 +$dir =~ s%/\.\.(?=/)%__%g;              # Don't allow foo/../../etc 
 + 
 +# For "foo", allow "​foo",​ "​foo/"​ and "​foo/​anything"​. 
 +# For "​foo/​bar"​ and "​foo/​anything/​bar",​ interpret "​bar"​ to be the specified 
 +# path and "​bar/"​ to be the specified path with trailing slash supplied. 
 + 
 +my($target,​$forced);​ 
 +if      ("/​$dir"​ eq substr($top1,​-length("/​$dir"​))) { 
 +  $target ​$top1; ​                     # Matched end of path 
 +} elsif ("/​$dir"​ eq substr($top2,​-length("/​$dir"​))) { 
 +  $target ​$top2; ​                     # End of path plus trailing slash 
 +} elsif ($dir eq $top1 or index($dir,​$top2) ​== 0) { 
 +  $target ​$dir;                       # Exact match or subdirectory 
 +} elsif (substr($dir,​0,​1) eq '/'​) { 
 +  $target ​"​$top1$dir"; ​               # Nonmatching absolute path 
 +  $forced = 1; 
 +} else { 
 +  $target ​= "$top2$dir"; ​               # Nonmatching relative path 
 +  $forced = 1; 
 +
 + 
 +$target =~ s#^//#/#; # program is dumb and sets root to '//'​ sometimes, which confuses windows/​cygwin hosts into looking for a share 
 + 
 +if (-f LOGFILE and open LOG,'>>',​LOGFILE) { 
 +  my $hhmm = sprintf "​%02d:​%02d",​(localtime)[2,​1];​ 
 +  my $host = $ENV{SSH_CLIENT} || '​unknown';​ 
 +  $host =~ s.*//;                     # Keep only the client'​s IP addr 
 +  $host = gethostbyaddr(inet_aton($host),​AF_INET) || $host; 
 +  $_ = sprintf "​%-13s",​$host;​ 
 +  print LOG "$hhmm $_ [$command] =",​($forced ? "> $target"​ : ' OK'​),"​\n";​ 
 +  close LOG; 
 +
 + 
 +exec "$cmd $target"​ or die "​exec($cmd $target) failed: $? $!"; 
 +# Note: This assumes that the rsync protocol will not be maliciously hijacked.
 </​code>​ </​code>​
  
-  * Set up a "​Scheduled task" in the Control Panel to run the thing daily or whatever.+For Windows targets, install cygwin'​s SSH and rsync as per this guide The rsnapshot.conf lines for such hosts should look something like: 
 + 
 +  backup windowsuser@windowsbox-rsnapshot:/​d/​Documents windowsbox/​ rsync_long_args=--no-numeric-ids --delete --relative --delete-excluded
efficient_backups_with_rsnapshot.1259766497.txt.gz · Last modified: 2009/12/02 07:08 by tkbletsc