From: Wayne Davison Date: Thu, 30 Dec 2021 20:29:14 +0000 (-0800) Subject: Add error-code ignoring options to atomic-rsync. X-Git-Tag: v3.2.4pre1~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=13cfe6406fbf73d20fff9213656d94e21ac0289a;p=thirdparty%2Frsync.git Add error-code ignoring options to atomic-rsync. --- diff --git a/NEWS.md b/NEWS.md index 735dec1d..aed80b59 100644 --- a/NEWS.md +++ b/NEWS.md @@ -97,7 +97,7 @@ - More ASM optimizations from Shark64. - - Transformed rrsync into a python script with improvements: + - Transformed support/rrsync into a python script with improvements: - Security has been beefed up. - The known rsync options were updated to include recent additions. - Make rrsync reject `-L`, `-K`, & `-k` by default to make it harder to @@ -112,6 +112,17 @@ and to output the command executed as a tuple (making the args clearer). - An rrsync.1 manpage was added. + - Added options to support/lsh to allow the rrsync script to be easily tested. + + - Transformed support/atomic-rsync into a python script and added the ability + to ignore one or more non-zero exit codes. By default, it now ignores code + 24 (file vanished). + + - Improved support/rsync-no-vanished wrapper script to not join stdout & + stderr together. + + - Transformed support/munge-symlinks into a python script. + - Work around a glibc bug where lchmod() breaks in a chroot w/o /proc mounted. - Some manpage improvements. diff --git a/support/atomic-rsync b/support/atomic-rsync index 37363e43..1964090d 100755 --- a/support/atomic-rsync +++ b/support/atomic-rsync @@ -29,6 +29,13 @@ def main(): if bad_args: die("You cannot use the", ' or '.join(bad_args), "option with atomic-rsync.\nUse --help for help.") + # We ignore exit-code 24 (file vanished) by default. + allowed_exit_codes = '0 ' + os.environ.get('ATOMIC_RSYNC_OK_CODES', '24') + try: + allowed_exit_codes = set(int(num) for num in re.split(r'[, ]+', allowed_exit_codes) if num != '') + except ValueError: + die('Invalid integer in ATOMIC_RSYNC_OK_CODES:', allowed_exit_codes[2:]) + symlink_content = os.readlink(dest_dir) if os.path.islink(dest_dir) else None dest_arg = dest_dir @@ -55,14 +62,18 @@ def main(): if os.path.isdir(new_dir): shutil.rmtree(new_dir) - subprocess.run([RSYNC_PROG, '--link-dest=' + dest_dir, *cmd_args], check=True) + child = subprocess.run([RSYNC_PROG, '--link-dest=' + dest_dir, *cmd_args]) + if child.returncode not in allowed_exit_codes: + die('The rsync copy failed with code', child.returncode, exitcode=child.returncode) + + if not os.path.isdir(new_dir): + die('The rsync copy failed to create:', new_dir) if old_dir is None: atomic_symlink(symlink_content, dest_arg) - return - - os.rename(dest_dir, old_dir) - os.rename(new_dir, dest_dir) + else: + os.rename(dest_dir, old_dir) + os.rename(new_dir, dest_dir) def atomic_symlink(target, link): @@ -89,22 +100,24 @@ to a local directory, and that directory must already exist. For example: ln -s files-1 /local/files atomic-rsync -aiv host:/remote/files/ /local/files/ -If /local/files is a symlink to a directory that ends in -1 or -2, the -copy will go to the alternate suffix and the symlink will be changed to -point to the new dir. This is a fully atomic update. If the destination -is not a symlink (or not a symlink to a *-1 or a *-2 directory), this -will instead create a directory with "~new~" suffixed, move the current -directory to a name with "~old~" suffixed, and then move the ~new~ -directory to the original destination name (this double rename is not -fully atomic, but is rapid). In both cases, the prior destintaion -directory will be preserved until the next update, at which point it -will be deleted. +If /local/files is a symlink to a directory that ends in -1 or -2, the copy +will go to the alternate suffix and the symlink will be changed to point to +the new dir. This is a fully atomic update. If the destination is not a +symlink (or not a symlink to a *-1 or a *-2 directory), this will instead +create a directory with "~new~" suffixed, move the current directory to a +name with "~old~" suffixed, and then move the ~new~ directory to the original +destination name (this double rename is not fully atomic, but is rapid). In +both cases, the prior destintaion directory will be preserved until the next +update, at which point it will be deleted. -In all likelihood, you do NOT want to specify this command: +By default, rsync exit-code 24 (file vanished) is allowed without halting the +atomic update. If you want to change that, specify the environment variable +ATOMIC_RSYNC_OK_CODES with numeric values separated by spaces and/or commas. +Specify an empty string to only allow a successful copy. An override example: - atomic-rsync -aiv host:/remote/files /local/ + ATOMIC_RSYNC_OK_CODES='23 24' atomic-rsync -aiv host:src/ dest/ -... UNLESS you want the entire /local dir to be swapped out! +See the errcode.h file for a list of all the exit codes. See the "rsync" command for its list of options. You may not use the --link-dest, --compare-dest, or --copy-dest options (since this script @@ -114,9 +127,9 @@ uses --link-dest to make the transfer efficient). sys.exit(1 if use_stderr else 0) -def die(*args): +def die(*args, exitcode=1): print(*args, file=sys.stderr) - sys.exit(1) + sys.exit(exitcode) if __name__ == '__main__':