class Rsyncbackup

Constants

DEFAULT_EXCLUSIONS
DEFAULT_INCOMPLETE_DIR_NAME
DEFAULT_LAST_FULL_DIR_NAME
VERSION

Attributes

error[RW]
options[RW]
output[RW]
source[RW]
status[RW]
target[RW]

Public Class Methods

new(source, target, opts={}) click to toggle source
# File lib/rsyncbackup.rb, line 11
def initialize(source, target, opts={})
  logger.level = Logger::WARN
  logger.level = Logger::INFO if opts[:verbose]
  logger.error_level = Logger::DEBUG if opts[:debug]

  raise "Unknown target: #{target}" unless File.exist?(target) or opts[:dry_run]

  @source     = strip_trailing_separator_if_any(source,true)
  @target     = strip_trailing_separator_if_any(target)

  @options = {
    :dry_run         => false,
    :exclusions      => DEFAULT_EXCLUSIONS,
    :archive         => true,
    :one_file_system => true,
    :hard_links      => true,
    :human_readable  => true,
    :inplace         => true,
    :numeric_ids     => true,
    :delete          => true,
    :link_dest       => last_full_backup,
    :rsync_cmd       => rsync_executable
  }.merge(opts)
  
  @incomplete = File.join(target,DEFAULT_INCOMPLETE_DIR_NAME)
  @complete   = File.join(target,backup_dir_name)
  
  
  debug "#{caller(0,1).first} @source: #{@source}, @target: #{@target}, @options: #{@options.inspect}"

end

Public Instance Methods

_run_the_command(cmd) click to toggle source
# File lib/rsyncbackup/utilities.rb, line 16
def _run_the_command(cmd)
  Open3.popen3(cmd) do |stdin, stdout, stderr, t|
    pid = t.pid
    stdin.close
    err_thr = Thread.new { copy_lines(stderr, $stderr) }
    debug "#{caller(0,1).first} Reading STDOUT"
    copy_lines(stdout, $stdout)
    err_thr.join
    t.value
  end
end
backup_dir_name() click to toggle source

returns the directory name for the current backup directory name consists of a time format: YYYY-MM-DDTHH-MM-SS

# File lib/rsyncbackup/utilities.rb, line 86
def backup_dir_name
  @backup_dir_name ||= Time.now.strftime("%FT%H-%M-%S")
end
build_command() click to toggle source

returns the command string to execute with all parameters set

# File lib/rsyncbackup/utilities.rb, line 41
def build_command
  
  cmd = []
  cmd << options[:rsync_cmd]
  cmd << '--dry-run'             if options[:dry_run]
  cmd << '--verbose --progress --itemize-changes' if (options[:verbose] || options[:debug])
  cmd << '--archive'             if options[:archive]
  cmd << '--one-file-system'     if options[:one_file_system]
  cmd << '--hard-links'          if options[:hard_links]
  cmd << '--human-readable'      if options[:human_readable]
  cmd << '--inplace'             if options[:inplace]
  cmd << '--numeric-ids'         if options[:numeric_ids]
  cmd << '--delete'              if options[:delete]
  cmd << "--exclude-file #{options[:exclusions]}" if File.exist?(options[:exclusions])
  cmd << "--link-dest '#{options[:link_dest]}'" if options[:link_dest]
  cmd << ?" + @source + ?"
  cmd << ?" + temp_target_path + ?"
  
  cmd.join(' ')
  
end
copy_lines(str_in, str_out) click to toggle source
# File lib/rsyncbackup/utilities.rb, line 28
def copy_lines(str_in, str_out)
  str_in.each_line {|line| str_out.puts line}
end
finalize() click to toggle source
# File lib/rsyncbackup.rb, line 65
def finalize
  File.rename(@incomplete, @complete) if File.exist?(@incomplete)
  File.write(File.join(@target,DEFAULT_LAST_FULL_DIR_NAME), backup_dir_name)
  info "Backup saved in #{@complete}"
end
full_target_path() click to toggle source

returns the full target path, including backup directory name

# File lib/rsyncbackup/utilities.rb, line 91
def full_target_path
  @full_target_path ||= File.join(@target, backup_dir_name)
end
last_full_backup() click to toggle source

returns the directory name of the last full backup returns nil otherwise

# File lib/rsyncbackup/utilities.rb, line 65
def last_full_backup
  
  unless @last_full_backup
    lastfull = File.join(@target,DEFAULT_LAST_FULL_DIR_NAME)
    @last_full_backup = unless File.exist?(lastfull)
                          nil
                        else
                          last_full_directory = IO.readlines(lastfull).first.chomp
                       unless File.exist?(File.join(@target,last_full_directory))
                            nil
                          else
                            last_full_directory
                          end
                        end
  end
  @last_full_backup

end
rsync_executable() click to toggle source

returns the path to the rsync executable If none found, raises an Exception

# File lib/rsyncbackup/utilities.rb, line 104
def rsync_executable
  rsync = `which rsync`.chomp
  raise "No rsync executable. Are you sure it\'s installed?" if rsync.empty?
  rsync
end
run() click to toggle source
# File lib/rsyncbackup.rb, line 44
def run
  @cmd = build_command
  
  info "Backing up #{@source} to #{@target} on #{Time.now}"
  info "Rsync command: #{@cmd}"
  info "Dry run only" if options[:dry_run]
    
  if File.exist? temp_target_path
    warn "Preexisting temporary target. Moving it aside."
    File.rename temp_target_path, "#{temp_target_path}-#{Time.now.to_i}"
  end

  # the dry run option will be passed through to the rsync command,
  # so we still do want to run it.
  self.status = _run_the_command(@cmd)
  debug "#{caller(0,1).first} self.status #{self.status.inspect}"
  raise "Rsync Error: exit status: #{self.status.exitstatus}" unless (self.status.success? || self.status.exitstatus == 23) # don't abort if some files could not be transferred
  finalize
  self
end
strip_trailing_separator_if_any(s,keep_if_symlink=false) click to toggle source

Strip the trailing directory separator from the rsync source or target.

s

string to strip

# File lib/rsyncbackup/utilities.rb, line 114
def strip_trailing_separator_if_any(s,keep_if_symlink=false)
  s = s.to_s
  s_s = s.sub(%r{#{File::SEPARATOR}+$},'')
  unless keep_if_symlink
    s_s
  else
    File.symlink?(s_s) ? s : s_s
  end
end
success?() click to toggle source

returns true if the rsync command was successful

# File lib/rsyncbackup/utilities.rb, line 35
def success?
  (@status.nil?) ? nil : @status.success?
end
temp_target_path() click to toggle source

returns the temporary target path

# File lib/rsyncbackup/utilities.rb, line 96
def temp_target_path
  @temp_target_path ||= File.join(@target, DEFAULT_INCOMPLETE_DIR_NAME)
end