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' |