From 1d1df99ee8d0bc4ec587fd2bfd412f4bb0edd200 Mon Sep 17 00:00:00 2001 From: Andrew Burkett Date: Tue, 26 Nov 2019 21:22:27 -0800 Subject: [PATCH] Add locking of borgmatic config file This prevents multiple instances of borgmatic from running against the same config file. This is particularly important when there are pre-backup scripts with side effects --- borgmatic/commands/borgmatic.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index 4cd63bb4..94d709f2 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -566,9 +566,25 @@ def main(): # pragma: no cover logger.debug('Ensuring legacy configuration is upgraded') convert.guard_configuration_upgraded(LEGACY_CONFIG_PATH, config_filenames) + locks = [] + for config_filename,config in configs.items(): + lock_config = config.get("location",dict()).get("lock_config",False) + if lock_config: + f = open(config_filename) + try: + fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) + except IOError: + logger.critical("Failed to acquire lock for {}".format(config_filename)) + sys.exit(0)) + locks.append(f) + summary_logs = parse_logs + list(collect_configuration_run_summary_logs(configs, arguments)) summary_logs_max_level = max(log.levelno for log in summary_logs) + # this removes the reference to the open files which python will garbage collect the file objects + # and close them + locks = None + for message in ('', 'summary:'): log_record( levelno=summary_logs_max_level,