diff options
| -rwxr-xr-x | byteback-backup | 169 | ||||
| -rwxr-xr-x | byteback-prune | 116 | ||||
| -rwxr-xr-x | byteback-receive | 41 | ||||
| -rwxr-xr-x | byteback-restore | 110 | ||||
| -rwxr-xr-x | byteback-snapshot | 30 | 
5 files changed, 220 insertions, 246 deletions
| diff --git a/byteback-backup b/byteback-backup index 202323d..ac9165a 100755 --- a/byteback-backup +++ b/byteback-backup @@ -8,7 +8,7 @@  require 'resolv' -$LOAD_PATH.unshift("/usr/lib/byteback") +$LOAD_PATH.unshift('/usr/lib/byteback')  require 'trollop'  require 'byteback/util' @@ -16,50 +16,47 @@ require 'byteback/log'  include Byteback::Util  include Byteback::Log +ME = $PROGRAM_NAME.split('/').last -ME = $0.split("/").last - -opts = Trollop::options do - +opts = Trollop.options do    banner "#{ME}: Back up this system to a byteback-enabled server\n " -  opt :destination, "Backup destination (i.e. user@host:/path)", -      :type => :string +  opt :destination, 'Backup destination (i.e. user@host:/path)', +      type: :string -  opt :source, "Source paths", -      :type => :strings, -      :default => ["/"] +  opt :source, 'Source paths', +      type: :strings, +      default: ['/'] -  opt :exclude, "Paths to exclude", -      :type => :strings, -      :short => "x" +  opt :exclude, 'Paths to exclude', +      type: :strings, +      short: 'x' -  opt :verbose, "Show debugging messages" +  opt :verbose, 'Show debugging messages' -  opt :retry_number, "Number of retries on error", -      :type => :integer, -      :default => 3 +  opt :retry_number, 'Number of retries on error', +      type: :integer, +      default: 3 -  opt :retry_delay, "Number of seconds between retries after an error", -      :type => :integer, -      :default => 300 +  opt :retry_delay, 'Number of seconds between retries after an error', +      type: :integer, +      default: 300 -  opt :ssh_key, "SSH key filename", -      :type => :string, -      :default => "/etc/byteback/key", -      :short => "k" +  opt :ssh_key, 'SSH key filename', +      type: :string, +      default: '/etc/byteback/key', +      short: 'k' -  opt :help, "Show this message", -      :short => "h" +  opt :help, 'Show this message', +      short: 'h'    banner "\nAdditional excludes can be specified using /etc/byteback/rsync_filter, which is an rsync filter file.  See the rsync man page for information on how this works.\n" -  end -lock_out_other_processes("byteback-backup") +lock_out_other_processes('byteback-backup')  @ssh_key = opts[:ssh_key] -@verbose = opts[:verbose] ? "--verbose" : nil +@verbose = opts[:verbose] ? '--verbose' : nil  @sources = opts[:source] if opts[:source]  @excludes = opts[:exclude] if opts[:exclude]  @destination = opts[:destination] @@ -67,33 +64,33 @@ lock_out_other_processes("byteback-backup")  @retry_delay = opts[:retry_delay]  # Read the default destination -if File.exists?("/etc/byteback/destination") -  @destination = File.read("/etc/byteback/destination").chomp +if File.exist?('/etc/byteback/destination') +  @destination = File.read('/etc/byteback/destination').chomp  end  # Set the default SSH key -if File.exists?("/etc/byteback/key") -  @ssh_key = "/etc/byteback/key" +if File.exist?('/etc/byteback/key') +  @ssh_key = '/etc/byteback/key'  end  #  # Check our destination  #  if @destination =~ /^(?:(.+)@)?([^@:]+):(.+)?$/ -  @destination_user, @destination_host, @destination_path = [$1, $2, $3] +  @destination_user, @destination_host, @destination_path = [Regexp.last_match(1), Regexp.last_match(2), Regexp.last_match(3)]  else -  fatal("Destination must be a remote path, e.g. ssh@host.com:/store/backups") +  fatal('Destination must be a remote path, e.g. ssh@host.com:/store/backups')  end  #  # Validate & normalise source directories  # -@sources = ["/"] if @sources.nil? +@sources = ['/'] if @sources.nil? -fatal("No sources specified") if @sources.empty? +fatal('No sources specified') if @sources.empty?  @sources = @sources.map do |s| -  s = s.gsub(/\/+/,"/") +  s = s.gsub(/\/+/, '/')    fatal("Can't read directory #{s}") unless File.readable?(s)    s  end @@ -119,36 +116,36 @@ if @excludes.nil?    )    COMMON_JUNK = %w( -     /swap.file -     /tmp -     /var/backups/localhost -     /var/cache/apt/archives -     /var/lib/php5 -     /var/tmp +    /swap.file +    /tmp +    /var/backups/localhost +    /var/cache/apt/archives +    /var/lib/php5 +    /var/tmp    ) -  MOUNT_HEADINGS = %w( spec file vfstype mntops freq passno ). -    map(&:to_sym) +  MOUNT_HEADINGS = %w( spec file vfstype mntops freq passno ) +                   .map(&:to_sym) -  mounts = File.read("/proc/mounts").split("\n").map do |line| -    Hash[MOUNT_HEADINGS.zip(line.split(" "))] +  mounts = File.read('/proc/mounts').split("\n").map do |line| +    Hash[MOUNT_HEADINGS.zip(line.split(' '))]    end    @excludes = -    mounts. -      select { |m| !PROBABLY_LOCAL.include?(m[:vfstype]) }. -      map { |m| m[:file] } + +    mounts +    .select { |m| !PROBABLY_LOCAL.include?(m[:vfstype]) } +    .map { |m| m[:file] } + -    COMMON_JUNK.select { |f| File.exists?(f) } +    COMMON_JUNK.select { |f| File.exist?(f) }  end  @excludes = @excludes.map do |e| -  e.gsub(/\/+/,"/") +  e.gsub(/\/+/, '/')  end -fatal("Must suply --destination or put it into /etc/bytebackup/destination") unless @destination +fatal('Must suply --destination or put it into /etc/bytebackup/destination') unless @destination  #  # Test ssh connection is good before we start @@ -156,25 +153,25 @@ fatal("Must suply --destination or put it into /etc/bytebackup/destination") unl  fatal("Could not read ssh key #{@ssh_key}") unless File.readable?(@ssh_key)  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 : "" } +  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 : '' }    log_system(*args)  end  fatal("Could not connect to #{@destination}") unless -  ssh("byteback-receive", "--ping", @verbose) == 0 +  ssh('byteback-receive', '--ping', @verbose) == 0  #  # Call rsync to copy certain sources, returns exit status (see man rsync) @@ -192,32 +189,32 @@ def rsync(*sources)    #    args = %w( rsync --archive --numeric-ids --delete-delay --inplace --relative --timeout 43200 ) -  args += [ "--rsh", "ssh -o BatchMode=yes -x -a -i #{@ssh_key} -l #{@destination_user}"] -  args << "--verbose" if @verbose -  args += @excludes.map { |x| ["--exclude", x] }.flatten +  args += ['--rsh', "ssh -o BatchMode=yes -x -a -i #{@ssh_key} -l #{@destination_user}"] +  args << '--verbose' if @verbose +  args += @excludes.map { |x| ['--exclude', x] }.flatten    #    # Add in the rsync excludes and sources files, if present.    # -  if File.exists?("/etc/byteback/excludes") -      args += ["--exclude-from", "/etc/byteback/excludes"] +  if File.exist?('/etc/byteback/excludes') +    args += ['--exclude-from', '/etc/byteback/excludes']    end    #    # Add in an rsync_filter if required.    # -  if File.exists?("/etc/byteback/rsync_filter") -      args += ["--filter", "merge /etc/byteback/rsync_filter"] +  if File.exist?('/etc/byteback/rsync_filter') +    args += ['--filter', 'merge /etc/byteback/rsync_filter']    end    #    # To add extra rsync flags, a file can be used.  This can have flags all on one line, or one per line.    # -  if File.exists?("/etc/byteback/rsync_flags") -    args += File.readlines("/etc/byteback/rsync_flags").map(&:chomp) +  if File.exist?('/etc/byteback/rsync_flags') +    args += File.readlines('/etc/byteback/rsync_flags').map(&:chomp)    end -  args += [ "--rsync-path", "rsync --fake-super"] +  args += ['--rsync-path', 'rsync --fake-super']    args += sources    args << @destination @@ -231,16 +228,16 @@ end  # on some hosts the backup process never finishes.  #  RSYNC_EXIT_STATUSES_TO_ACCEPT   = [0, 24] -RSYNC_EXIT_STATUSES_TO_RETRY_ON = [10,11,20,21,22,23,30] +RSYNC_EXIT_STATUSES_TO_RETRY_ON = [10, 11, 20, 21, 22, 23, 30]  # Run the file copy, retrying if necessary  #  loop do    status = rsync(*@sources) -  if RSYNC_EXIT_STATUSES_TO_ACCEPT.any?{|s| s === status} +  if RSYNC_EXIT_STATUSES_TO_ACCEPT.any? { |s| s === status }      break -  elsif RSYNC_EXIT_STATUSES_TO_RETRY_ON.any?{|s| s === status} +  elsif RSYNC_EXIT_STATUSES_TO_RETRY_ON.any? { |s| s === status }      warn "rsync exited with status #{status}" @@ -250,18 +247,18 @@ loop do        sleep @retry_delay        redo      else -      fatal("Maximum number of rsync retries reached") +      fatal('Maximum number of rsync retries reached')      end    else      fatal("Fatal rsync error occurred (#{status})")    end  end -info("Backup completed, requesting snapshot") +info('Backup completed, requesting snapshot')  # Mark the backup as done on the other end  # -fatal("Backup could not be marked complete") unless -  ssh("byteback-receive", "--complete", @verbose) == 0 +fatal('Backup could not be marked complete') unless +  ssh('byteback-receive', '--complete', @verbose) == 0 -info("Finished") +info('Finished') diff --git a/byteback-prune b/byteback-prune index 28ef2bf..d005289 100755 --- a/byteback-prune +++ b/byteback-prune @@ -4,7 +4,7 @@  # backups (whether by age, or importance).  # -$LOAD_PATH.unshift("/usr/lib/byteback") +$LOAD_PATH.unshift('/usr/lib/byteback')  require 'trollop'  require 'byteback' @@ -13,30 +13,28 @@ include Byteback  include Byteback::Log  include Byteback::Util -opts = Trollop::options do +opts = Trollop.options do +  banner "Prune old backup directories to ensure there's enough space" -    banner "Prune old backup directories to ensure there's enough space" +  opt :minpercent, 'Start prune when disk has less than this %age free', +      type: :integer, +      default: 5 -    opt :minpercent, "Start prune when disk has less than this %age free", -        :type => :integer, -        :default => 5 +  opt :maxpercent, 'Stop prune when disk has more than this %age free', +      type: :integer, +      default: 10 -    opt :maxpercent, "Stop prune when disk has more than this %age free", -        :type => :integer, -        :default => 10 +  opt :list, 'List backups in pruning order, no other action' -    opt :list, "List backups in pruning order, no other action" +  opt :prune, 'Prune the next backup if necessary' -    opt :prune, "Prune the next backup if necessary" +  opt :prune_force, 'Prune the next backup regardless' -    opt :prune_force, "Prune the next backup regardless" - -    opt :order, "Order backups by 'age' or 'importance'", -    	:type => :string, -    	:default => "importance" - -    opt :verbose, "Show debugging messages" +  opt :order, "Order backups by 'age' or 'importance'", +      type: :string, +      default: 'importance' +  opt :verbose, 'Show debugging messages'  end  @order = opts[:order] @@ -49,7 +47,7 @@ end  @do_prune = true if @do_prune_force -fatal("Must specify one of --prune or --list") unless +fatal('Must specify one of --prune or --list') unless    (@do_prune || @do_list) &&    !(@do_prune && @do_list) @@ -57,24 +55,24 @@ fatal("Must specify --order as 'age' or 'importance'") unless    @order == 'age' || @order == 'importance'  if BackupDirectory.all.empty? -	fatal("No backup directories found, need to run byteback-snapshot") +  fatal('No backup directories found, need to run byteback-snapshot')  end -lock_out_other_processes("byteback-prune") +lock_out_other_processes('byteback-prune')  @df_history = DiskFreeHistory.new(ENV['HOME'])  begin -	@df_history.new_reading! +  @df_history.new_reading!  rescue Errno::ENOSPC -	if @do_list -		warn("Couldn't write disk history file due to lack of space, ignoring") -	else -		warn("Couldn't write disk history file due to lack of space, going to --prune-force") -		@do_prune = @do_prune_force = true -	end +  if @do_list +    warn("Couldn't write disk history file due to lack of space, ignoring") +  else +    warn("Couldn't write disk history file due to lack of space, going to --prune-force") +    @do_prune = @do_prune_force = true +  end  rescue => anything_else -	error("Couldn't record disk history of #{@df_history.mountpoint} in #{@df_history.history_file}, installation problem?") -	raise +  error("Couldn't record disk history of #{@df_history.mountpoint} in #{@df_history.history_file}, installation problem?") +  raise  end  gradient_30m = @df_history.gradient(1800) @@ -85,57 +83,57 @@ gradient_30m = @df_history.gradient(1800)  PRUNING_FLAG = "#{ENV['HOME']}/.byteback.pruning"  if @do_prune_force -	info("Forcing prune") -elsif @free <= @minpercent && !File.exists?(PRUNING_FLAG) -	info("Starting prune #{@free}% -> #{@maxpercent} free") -	File.write(PRUNING_FLAG,"") -elsif @free >= @maxpercent && File.exists?(PRUNING_FLAG) -	info("Stopping prune, reached #{@free}% free") -	File.unlink(PRUNING_FLAG) -elsif File.exists?(PRUNING_FLAG) -	info("Continuing prune #{@free}% -> #{@maxpercent}, gradient = #{gradient_30m}") +  info('Forcing prune') +elsif @free <= @minpercent && !File.exist?(PRUNING_FLAG) +  info("Starting prune #{@free}% -> #{@maxpercent} free") +  File.write(PRUNING_FLAG, '') +elsif @free >= @maxpercent && File.exist?(PRUNING_FLAG) +  info("Stopping prune, reached #{@free}% free") +  File.unlink(PRUNING_FLAG) +elsif File.exist?(PRUNING_FLAG) +  info("Continuing prune #{@free}% -> #{@maxpercent}, gradient = #{gradient_30m}")  end  debug("Disc free #{@free}%, 30m gradient = #{gradient_30m}")  def snapshots_in_order -	list = BackupDirectory.all_snapshots -	if @order == 'importance' -		Snapshot.sort_by_importance(list) -	elsif @order == 'age' -		list.sort.reverse -	else -		raise ArgumentError.new("Unknown snapshot sort method #{method}") -	end +  list = BackupDirectory.all_snapshots +  if @order == 'importance' +    Snapshot.sort_by_importance(list) +  elsif @order == 'age' +    list.sort.reverse +  else +    fail ArgumentError.new("Unknown snapshot sort method #{method}") +  end  end  snapshots = snapshots_in_order  if @do_list -	print "Backups by #{@order}:\n" -	snapshots.each_with_index do |snapshot, index| -		print "#{sprintf('% 3d',index)}: #{snapshot.path}\n" -	end +  print "Backups by #{@order}:\n" +  snapshots.each_with_index do |snapshot, index| +    print "#{sprintf('% 3d', index)}: #{snapshot.path}\n" +  end  end  # Don't do anything if we've not got two hours of readings  # -if !@do_prune_force -    if @df_history.list.last.time - @df_history.list.first.time < 1800 -	    warn("Not enough disc space history to make a decision") -	    exit 0 -    end +unless @do_prune_force +  if @df_history.list.last.time - @df_history.list.first.time < 1800 +    warn('Not enough disc space history to make a decision') +    exit 0 +  end  end  exit 0 unless -  (@do_prune && File.exists?(PRUNING_FLAG)) || +  (@do_prune && File.exist?(PRUNING_FLAG)) ||    @do_prune_force  exit 0 unless @do_prune_force || gradient_30m == 0  if snapshots.empty? -	error("No snapshots to delete, is there enough disc space?") -	exit 1 +  error('No snapshots to delete, is there enough disc space?') +  exit 1  end  info("Deleting #{snapshots.last.path}") diff --git a/byteback-receive b/byteback-receive index 23282db..4b949c2 100755 --- a/byteback-receive +++ b/byteback-receive @@ -9,26 +9,25 @@ require 'trollop'  require 'byteback'  include Byteback::Log -  if ENV['SSH_ORIGINAL_COMMAND'] -	ARGV.concat(ENV['SSH_ORIGINAL_COMMAND'].split(" ")) +  ARGV.concat(ENV['SSH_ORIGINAL_COMMAND'].split(' '))  end  byteback_host = ENV['BYTEBACK_HOST'] -fatal("BYTEBACK_HOST environment not set") unless byteback_host +fatal('BYTEBACK_HOST environment not set') unless byteback_host -byteback_root = ENV['HOME'] + "/" + ENV["BYTEBACK_HOST"] +byteback_root = ENV['HOME'] + '/' + ENV['BYTEBACK_HOST']  fatal("#{byteback_root} does not exist") unless File.directory?(byteback_root)  #  #  Force restores to be limited to the hostname we're connecting form  # -if ( ARGV[0] == 'restore' ) +if (ARGV[0] == 'restore')    ARGV[0] = 'rsync'    a = []    ARGV.each do |tmp| -    if ( tmp =~ /^\/(.*)/ ) -      tmp = "#{byteback_host}/#{$1.dup}" +    if  tmp =~ /^\/(.*)/ +      tmp = "#{byteback_host}/#{Regexp.last_match(1).dup}"      end      a.push(tmp)    end @@ -37,27 +36,27 @@ elsif ARGV[0] == 'rsync'    ARGV[-1] = "#{byteback_root}/current"    exec(*ARGV)  elsif ARGV[0] == 'byteback-snapshot' -  ARGV.concat(["--root", "#{byteback_root}"]) +  ARGV.concat(['--root', "#{byteback_root}"])    exec(*ARGV)  end -opts = Trollop::options do -	opt :verbose, "Print diagnostics" -	opt :ping, "Check connection parameters and exit" -	opt :list, "Show backed up files matching the given pattern", :type => :string -	opt :restore, "Perform a restoration operation", :type => :string -	opt :complete, "Mark current backup as complete" +opts = Trollop.options do +  opt :verbose, 'Print diagnostics' +  opt :ping, 'Check connection parameters and exit' +  opt :list, 'Show backed up files matching the given pattern', type: :string +  opt :restore, 'Perform a restoration operation', type: :string +  opt :complete, 'Mark current backup as complete'  end -error("Please only choose one mode") if opts[:ping] && opts[:complete] +error('Please only choose one mode') if opts[:ping] && opts[:complete]  if opts[:complete] -	system("byteback-snapshot", "--root", byteback_root) +  system('byteback-snapshot', '--root', byteback_root)  elsif opts[:list] -	system( "cd #{byteback_root} && find . -print | grep #{opts[:list]}" ) -	exit(0 ) +  system("cd #{byteback_root} && find . -print | grep #{opts[:list]}") +  exit(0)  elsif opts[:ping] -	exit 0 +  exit 0  else -	STDERR.print "byteback-receive failed\n" -	exit 9 +  STDERR.print "byteback-receive failed\n" +  exit 9  end diff --git a/byteback-restore b/byteback-restore index 9a6f3f0..48eea9a 100755 --- a/byteback-restore +++ b/byteback-restore @@ -3,50 +3,44 @@  # Restore a file from the most recent backup, from the remote host.  # -$LOAD_PATH.unshift("/usr/lib/byteback") -$LOAD_PATH.unshift("./lib/") +$LOAD_PATH.unshift('/usr/lib/byteback') +$LOAD_PATH.unshift('./lib/')  require 'trollop' -  #  #  Show an error message and abort.  # -def fatal( str ) -  STDERR.puts( str ) +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 : "" } +  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 ) +def list_files(pattern) +  ssh('byteback-receive', '--list', pattern)  end -  #  #  We cannot use plain 'rsync' here because the receiver command will  # see that, and rewrite our arguments. @@ -55,89 +49,77 @@ end  # do that by setting "rsync-path" to point to the receiver program.  #  # -def restore_file( path, revision ) +def restore_file(path, revision)    cmd = %w( rsync ) -  cmd += [ "--rsh", "ssh -o BatchMode=yes -x -a -i /etc/byteback/key -l byteback" ] -  cmd += [ "--rsync-path", "restore --fake-super" ] -  cmd += [ "-aApzrX",  "--numeric-ids" ] -  cmd += [ "#{@destination_host}:/#{revision}/#{path}", "." ] +  cmd += ['--rsh', 'ssh -o BatchMode=yes -x -a -i /etc/byteback/key -l byteback'] +  cmd += ['--rsync-path', 'restore --fake-super'] +  cmd += ['-aApzrX',  '--numeric-ids'] +  cmd += ["#{@destination_host}:/#{revision}/#{path}", '.']    system(*cmd) -  end - - - -  #  #  Parse our command-line arguments  # -opts = Trollop::options do - +opts = Trollop.options do    banner "byteback-restore: Restore a file\n " -  opt :file, "The file to restore", -      :type => :string +  opt :file, 'The file to restore', +      type: :string    opt :revision, "The version of the file to restore - default is 'latest'", -      :type => :string +      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" +  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") +@destination = File.read('/etc/byteback/destination').chomp if +  File.exist?('/etc/byteback/destination') +@ssh_key = '/etc/byteback/key' if File.exist?('/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? ) - +@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] +  @destination_user, @destination_host, @destination_path = [Regexp.last_match(1), Regexp.last_match(2), Regexp.last_match(3)]  else -  fatal("Destination must be a remote path, e.g. ssh@host.com:/store/backups") +  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" ) +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] ) +if  opts[:revision].nil? +  list_files(opts[:file])    exit(0)  end -  #  #  Restore a file  # -restore_file( opts[:file], opts[:revision] ) +restore_file(opts[:file], opts[:revision])  exit(0) diff --git a/byteback-snapshot b/byteback-snapshot index 6249d3d..fc9aab3 100755 --- a/byteback-snapshot +++ b/byteback-snapshot @@ -4,39 +4,37 @@  # using btrfs subvolume commands.  # -$LOAD_PATH.unshift("/usr/lib/byteback") +$LOAD_PATH.unshift('/usr/lib/byteback')  require 'trollop'  require 'byteback'  include Byteback  include Byteback::Log -opts = Trollop::options do +opts = Trollop.options do +  opt :root, 'Backups directory (must be a btrfs subvolume)', +      type: :string -    opt :root, "Backups directory (must be a btrfs subvolume)", -    	:type => :string - -    opt :snapshot, "(ignored for compatibility)" - -    opt :verbose, "Print diagnostics" +  opt :snapshot, '(ignored for compatibility)' +  opt :verbose, 'Print diagnostics'  end  @root = opts[:root]  @verbose = opts[:verbose] -fatal("--root not readable") unless File.directory?("#{@root}") +fatal('--root not readable') unless File.directory?("#{@root}")  @backups = BackupDirectory.new(@root)  snapshots = @backups.snapshots -if !snapshots.empty? -	last_snapshot_time = snapshots.last.time -	fatal("Last snapshot was less than six hours ago") unless -		!last_snapshot_time || -		Time.now - last_snapshot_time >= 6*60*60 # FIXME: make configurable +unless snapshots.empty? +  last_snapshot_time = snapshots.last.time +  fatal('Last snapshot was less than six hours ago') unless +    !last_snapshot_time || +    Time.now - last_snapshot_time >= 6 * 60 * 60 # FIXME: make configurable  end -info "Making new snapshot" +info 'Making new snapshot'  @backups.new_snapshot! -info "Finished" +info 'Finished' | 
