#!/bin/python3 import os import sys import json import shlex import subprocess import argparse import pathlib import socket import traceback import time restic_bin = 'restic' init_command = "restic -r %s init" command = "restic -r %s backup --verbose %s" hostname = socket.gethostname() print("This machine's hostname is " + hostname) def do_backup(repo_name, paths): result = subprocess.run([restic_bin, '-r', repo_name, 'backup', '--verbose'] + paths) def init_repo(repo_name): result = subprocess.run([restic_bin, '-r', repo_name, 'init'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) any_errors = len(result.stderr) > 0 already_existed = result.stderr.decode('utf-8').strip().endswith('config already exists') if any_errors and not already_existed: print(result.stderr.decode('utf-8').strip()) return False if already_existed: print("Repo already exists") return True print(result.stdout.decode('utf-8').strip()) print("Repo was created.") return True def cmd_backup(): result_info = [] with open('backup-config.json') as json_file: data = json.load(json_file) repo_name_prefix = data['repo_name_prefix'] for repo in data['repos']: if repo['hostname'] != hostname: print('(skipping ' + repo['name'] + ' since this machine is not ' + repo['hostname'] + ')') continue repo_name = repo_name_prefix + repo['name'] print('Repo: ' + repo_name) paths_to_backup = [shlex.quote(p) for p in repo['paths']] print('Backing up paths: ' + ", ".join(paths_to_backup)) init_result = init_repo(repo_name) if not init_result: print('Skipping backup of %s.' % repo_name) continue do_backup(repo_name, paths_to_backup) def cmd_mount(): processes = [] mount_points = [] with open('backup-config.json') as json_file: data = json.load(json_file) repo_name_prefix = data['repo_name_prefix'] mount_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "mnt_restic") for repo in data['repos']: repo_name = repo_name_prefix + repo['name'] repo_mount_path = os.path.join(mount_root, repo['name']) pathlib.Path(repo_mount_path).mkdir(parents=True, exist_ok=True) mount_process = subprocess.Popen([restic_bin, '-r', repo_name, 'mount', '--verbose', repo_mount_path]) processes.append(mount_process) mount_points.append(repo_mount_path) try: print("mounts starting. press ctrl+c to kill all mounts") while True: time.sleep(1) except KeyboardInterrupt: print("ctrl+c pressed. killing subprocesses") for proc in processes: proc.kill() print("you'll also want to umount these mount points:") for mp in mount_points: print("umount " + mp) except: print("unhandled exception") traceback.print_exc() def cmd_list(): with open('backup-config.json') as json_file: data = json.load(json_file) repo_name_prefix = data['repo_name_prefix'] for repo in data['repos']: repo_name = repo_name_prefix + repo['name'] print("restic -r %s " % repo_name) parser = argparse.ArgumentParser(description = "backup or mount many paths using restic") parser.add_argument('command', help='command to run (backup, mount, umount)') parser.add_argument('--resticbin', help='restic binary location, if not on PATH') args = parser.parse_args() # call function with the name. fn_name = "cmd_" + args.command if not fn_name in globals(): print("Command doesn't exist") parser.print_help() exit(1) if args.resticbin: restic_bin = args.resticbin globals()[fn_name]()