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