Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env ruby
- # Cleans up backup files transferred to a remote directory.
- # Place this file in the root of your backup account and it will clean up all
- # subdirectories. You may prevent or customize action by a config file.
- class Directory
- # The script will keep 24 hourly backups by default. So up to 24 files will
- # be kept that get stored on the server within one day.
- # After that, the latest of the hourly backups will be kept as daily backup.
- # 7 daily backups will be kept and on the 8th day, the backup of the 7th day
- # will be kept as backup for the week.
- # Same logic applies to weekly and monthly backups.
- CONFIG = {
- 'hourly' => 24, # Number of hourly backups to keep
- 'daily' => 7, # Number of daily backups to keep
- 'weekly' => 4, # Number of weekly backups to keep
- 'monthly' => 6, # Number of monthly backups to keep
- 'forever' => 5, # Number of backups to keep forever
- 'pattern' => '*.tar.gz', # Pattern to find files
- 'cleanup' => 'yes' # To prevent action, set 'no' (will affect all subdirs)
- }
- # Each default can be overwritten in a file .bakrm like this:
- # hourly: 4
- # daily: 2
- # weekly: 0
- # monthly: 0
- # forever: 4
- CONFIG_FILE = '.bakrm'
- def initialize(path)
- @path = path
- end
- # Returns folders
- def folders
- @folders ||= Dir.chdir(@path) do
- Dir.glob('*').
- select { |f| File.directory?(f) }.
- map { |f| File.join(@path, f) }
- end
- end
- # Returns files, sorted by date
- def files
- @files ||= Dir.chdir(@path) do
- Dir[pattern].
- reject { |f| %[bakrm.rb #{CONFIG_FILE}].include?(f) }.
- select { |f| File.file?(f) }.
- sort_by { |f| File.mtime(f) }.
- map { |f| File.join(@path, f) }.
- reverse
- end
- end
- def reload_files
- @files = nil
- files
- end
- # Returns config
- def config
- @config ||= begin
- path = File.join(@path, CONFIG_FILE)
- if File.exists?(path)
- text = File.read(path)
- values = text.scan(/(.+):\s*(.+)/)
- Hash[values]
- end
- end
- end
- def cleanup
- if cleanup?
- cleanup_files
- cleanup_folders
- end
- end
- private
- def cleanup_files
- reject_empty_files
- keep = keep_files
- delete = reload_files - keep
- # puts "keep: #{keep.count}; delete: #{delete.count}"
- delete.each { |f| File.delete(f) }
- end
- def cleanup_folders
- folders.each do |dir|
- Directory.new(dir).cleanup
- end
- end
- def config_value(key)
- value = config && config[key]
- value || CONFIG[key]
- end
- def cleanup?
- config_value('cleanup') == 'yes'
- end
- def pattern
- config_value('pattern')
- end
- def hourly
- config_value('hourly').to_i
- end
- def daily
- config_value('daily').to_i
- end
- def weekly
- config_value('weekly').to_i
- end
- def monthly
- config_value('monthly').to_i
- end
- def forever
- config_value('forever')
- end
- def keep_files
- keep = []
- keep += hourly_files if hourly > 0
- keep += daily_files if daily > 0
- keep += weekly_files if weekly > 0
- keep += monthly_files if monthly > 0
- keep.uniq!
- if keep.length < forever
- if files.length < forever
- keep = files
- else
- keep = files[0, forever]
- end
- end
- keep
- end
- def hourly_files
- pick_files(hourly, 3600)
- end
- def daily_files
- pick_files(daily, 3600*24)
- end
- def weekly_files
- pick_files(weekly, 3600*24*7)
- end
- def monthly_files
- pick_files(monthly, 3600*24*30)
- end
- # Remove empty files from list
- def reject_empty_files
- files.reject! { |f| File.size(f) == 0 }
- end
- # Pick files matching given time interval.
- def pick_files(counter, increment)
- picked = []
- range_start = now
- counter.times do
- range_end = range_start - increment
- files.each do |f|
- mtime = File.mtime(f)
- if mtime < range_start && mtime >= range_end
- picked << f
- break
- end
- end
- range_start = range_end
- end
- picked
- end
- def now
- @now ||= Time.now
- end
- end
- def run
- Directory.new(Dir.pwd).cleanup
- end
- run
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement