diff options
| -rwxr-xr-x | byteback-restore | 129 | 
1 files changed, 129 insertions, 0 deletions
| diff --git a/byteback-restore b/byteback-restore new file mode 100755 index 0000000..00964f1 --- /dev/null +++ b/byteback-restore @@ -0,0 +1,129 @@ +#!/usr/bin/ruby +# +# Restore a file from the most recent backup, from the remote host. +# + +$LOAD_PATH.unshift("/usr/lib/byteback") +$LOAD_PATH.unshift("./lib/") + +require 'trollop' + + +# +#  Show an error message and abort. +# +def fatal( str ) +  STDERR.puts( str ) +  exit(1) +end + + + +# +#  Run a remote command. +# +def ssh(*ssh_args) +  args = ["ssh", +    "-o", "BatchMode=yes", +    "-o", "ConnectionAttempts=5", +    "-o", "ConnectTimeout=30", +    "-o", "ServerAliveInterval=60", +    "-o", "TCPKeepAlive=yes", +    "-x", "-a", +    "-i", @ssh_key, +    "-l", @destination_user, +    @destination_host +  ] + +  ssh_args. +  map { |a| a ? a : "" } + +  system(*args) +end + + + +def list_files( pattern ) +  ssh("byteback-receive", "--list", pattern ) +end + + +def restore_file( path, revision ) +  puts "Restoring revision #{revision} of file #{path}" +end + + + + + +# +#  Parse our command-line arguments +# +opts = Trollop::options do + +  banner "byteback-restore: Restore a file\n " + +  opt :file, "The file to restore", +      :type => :string + +  opt :revision, "The version of the file to restore - default is 'latest'", +      :type => :string + +  opt :destination, "Backup destination (i.e. user@host:/path)", +      :type => :string + +  opt :ssh_key, "SSH key filename", +      :type => :string, +      :default => "/etc/byteback/key", +      :short => "k" + +end + + + +# +#  Setup default destination and key. +# +@destination = File.read("/etc/byteback/destination").chomp if +  File.exists?("/etc/byteback/destination") +@ssh_key = "/etc/byteback/key" if File.exists?("/etc/byteback/key") + +# +#  Allow the command-line to override them. +# +@ssh_key = opts[:ssh_key] unless( opts[:ssh_key].nil?) +@destination = opts[:destination] unless ( opts[:destination].nil? ) + + +# +# Check our destination is well-formed +# +if @destination =~ /^(?:(.+)@)?([^@:]+):(.+)?$/ +  @destination_user, @destination_host, @destination_path = [$1, $2, $3] +else +  fatal("Destination must be a remote path, e.g. ssh@host.com:/store/backups") +end + + +# +#  If the user didn't specify a file then we're not restoring anything, +# and we should abort. +# +if ( opts[:file].nil? ) +  fatal("You must specify a file to restore" ) +end + +# +#  If the user specified a file, but not a revision, then we list +# the available revisions. +# +if ( opts[:revision].nil? ) +  list_files( opts[:file] ) +  exit(0) +end + + +# +#  Restore a file +# +restore_file( opts[:file], opts[:revision] ) +exit(0) | 
