mirror of
https://codeberg.org/puppe/mpbackup.git
synced 2025-12-19 21:42:17 +01:00
99 lines
2.8 KiB
Ruby
99 lines
2.8 KiB
Ruby
#!/usr/bin/env ruby
|
||
require 'io/console'
|
||
require 'optparse'
|
||
require 'pathname'
|
||
require 'yaml'
|
||
|
||
ENV.delete('RESTIC_REPOSITORY')
|
||
ENV.delete('RESTIC_PASSWORD')
|
||
|
||
DEFAULT_CONFIG_FILE = Pathname.new('/etc/mpbackup/config.yaml')
|
||
|
||
options = {}
|
||
|
||
OptionParser.new do |parser|
|
||
parser.on("-f CONFIG_FILE", "--config-file CONFIG_FILE", "Path to config file") do |v|
|
||
options[:config_file] = v
|
||
end
|
||
|
||
parser.on("-h", "--help", "Prints this help") do
|
||
puts parser
|
||
exit
|
||
end
|
||
end.parse!
|
||
|
||
if options[:config_file]
|
||
config_file = Pathname.new(options[:config_file])
|
||
else
|
||
config_file = DEFAULT_CONFIG_FILE
|
||
end
|
||
|
||
if !Pathname.new(config_file).exist? then
|
||
STDERR.puts "Config file #{config_file} has not been found!"
|
||
exit 1
|
||
end
|
||
|
||
def do_backup(config)
|
||
puts "Applying configuration ‘#{config['name']}’ …"
|
||
ENV['RESTIC_REPOSITORY'] = config['repository']
|
||
puts "Repository: #{ENV['RESTIC_REPOSITORY']}"
|
||
if config['password-file']
|
||
puts "Reading password from file #{config['password-file']} …"
|
||
ENV['RESTIC_PASSWORD'] = File.open(config['password-file'], &:gets).chomp
|
||
else
|
||
ENV['RESTIC_PASSWORD'] = STDIN.getpass('Please put in your restic password: ')
|
||
end
|
||
|
||
puts "Backing up with restic …"
|
||
# https://restic.readthedocs.io/en/latest/040_backup.html#including-and-excluding-files
|
||
exclude = config.dig('backup', 'exclude')&.flat_map{|e| ['--exclude', e]} || []
|
||
paths = config.dig('backup', 'paths') || []
|
||
backup_command = ['restic', 'backup', *exclude, *paths]
|
||
puts("Command: #{backup_command.join(' ')}")
|
||
system(*backup_command)
|
||
if $?.exitstatus > 0
|
||
STDERR.puts 'Failed to do backup.'
|
||
exit 1
|
||
end
|
||
|
||
puts 'Checking restic repo …'
|
||
check_command = ['restic', 'check']
|
||
puts("Command: #{check_command.join(' ')}")
|
||
system(*check_command)
|
||
if $?.exitstatus > 0
|
||
STDERR.puts "Checking restic repository #{ENV['RESTIC_REPOSITORY']} failed."
|
||
exit 1
|
||
end
|
||
|
||
puts "Deleting unnecessary snapshots …"
|
||
flags = config['forget'].filter{|k,v| k != 'enable'}
|
||
flags = flags.flat_map{|k,v| ['--' + k, v.to_s]}
|
||
forget_command = ['restic', 'forget'] + flags
|
||
puts("Command: #{forget_command.join(' ')}")
|
||
system(*forget_command)
|
||
# Data will only be deleted when `restic prune` is executed or when
|
||
# `restic forget` is called with `--prune`.
|
||
if $?.exitstatus > 0
|
||
STDERR.puts "Forgetting snapshots failed."
|
||
exit 1
|
||
end
|
||
|
||
ENV.delete('RESTIC_REPOSITORY')
|
||
ENV.delete('RESTIC_PASSWORD')
|
||
end
|
||
|
||
puts "Using config file #{config_file} …"
|
||
configs = YAML.load_stream(File.open(config_file))
|
||
if ARGV.empty?
|
||
puts "No configuration name has been given. Will use the first "\
|
||
"configuration from the file (‘#{configs.dig(0, 'name')}’)."
|
||
do_backup(configs[0])
|
||
else
|
||
ARGV.each do |config_name|
|
||
configs.each do |config|
|
||
if config_name == config['name']
|
||
do_backup(config)
|
||
end
|
||
end
|
||
end
|
||
end
|