• R/O
  • SSH

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javaandroidc++linuxc#objective-ccocoa誰得qtrubypythonwindowsphpgamebathyscaphegui翻訳comegattwitterframeworkbtronvb.net計画中(planning stage)testdomarduinodirectxpreviewerゲームエンジン

rsync wrapper for pushing incremental backups


Commit MetaInfo

Revision8da194cd0eaea126a9bee0bc85cef0d471a13631 (tree)
Zeit2019-11-13 15:17:56
AutorFrank Tobin <ftobin@neve...>
CommiterFrank Tobin

Log Message

support storing permissions

Ändern Zusammenfassung

Diff

diff -r 7c0782056095 -r 8da194cd0eae rsnappush
--- a/rsnappush Wed Nov 06 00:01:48 2019 -0500
+++ b/rsnappush Wed Nov 13 01:17:56 2019 -0500
@@ -5,15 +5,19 @@
55
66 Author: Frank Tobin
77 Email: ftobin@neverending.org
8+Author URL: https://www.neverending.org/
89 License: Eclipse Public License 2.0 (https://opensource.org/licenses/EPL-2.0)
910 """
1011
1112 import os
1213 import re
1314 import sys
15+import lzma
1416 import time
1517 import argparse
1618 import subprocess
19+import tempfile
20+import shutil
1721
1822 parser = argparse.ArgumentParser(description="Perform file-based incremental rsync push backup with hard-links")
1923
@@ -24,10 +28,9 @@
2428 help="pass-thru options to rsync. Use '=' syntax, and include prefixing dashes. Example: --rsync-opt=--partial-dir=/home/user/rsync-partial")
2529 parser.add_argument("--quiet", "-q", action="store_true", default=False,
2630 help="emit less output")
27-parser.add_argument("--backup-prefix", default="backup-",
28- help="Prefix used in directory snapshots; default: 'backup-'")
29-parser.add_argument("--compare-n-backups", type=int, default=20,
30- help="How many previous backups to consider hard-linking against; default: 20 (rsync max)")
31+
32+backup_prefix = "backup-"
33+compare_n_backups = 20
3134
3235 args = parser.parse_args()
3336
@@ -40,33 +43,41 @@
4043 dest_account = None
4144 dest_path = args.dest
4245
43-mkdir_cmd = ["mkdir", "-p", dest_path]
44-if dest_account:
45- mkdir_cmd = ['ssh', dest_account] + mkdir_cmd
46+def ssh_prefix(cmd):
47+ if dest_account:
48+ cmd = ['ssh', dest_account] + cmd
49+ return cmd
50+
51+def rsync_quietness(cmd):
52+ if args.quiet:
53+ cmd.append("--quiet")
54+ else:
55+ cmd.extend(["-v", "--progress"])
56+ return cmd
57+
58+mkdir_cmd = ssh_prefix(["mkdir", "-p", dest_path])
4659 subprocess.run(mkdir_cmd, check=True)
4760
4861 # check what backups already exist
49-check_backups_cmd = ["ls", f"{dest_path}/"]
50-if dest_account:
51- check_backups_cmd = ['ssh', dest_account] + check_backups_cmd
62+check_backups_cmd = ssh_prefix(["ls", f"{dest_path}/"])
63+
5264 proc = subprocess.run(check_backups_cmd,
5365 stdout=subprocess.PIPE, encoding="utf-8", check=True)
54-
5566 link_dests = proc.stdout.splitlines()
56-link_dests = list(filter(lambda x: re.search(args.backup_prefix, x), link_dests))
57-link_dests = link_dests[-args.compare_n_backups:]
67+link_dests = list(filter(lambda x: re.search(backup_prefix, x), link_dests))
68+link_dests = link_dests[-compare_n_backups:]
5869 link_dest_args = list(map(lambda x: f"--link-dest=../{x}", link_dests))
5970
60-my_dest = time.strftime(f'{args.backup_prefix}%Y%m%d-%H:%M')
71+timestamp_str = time.strftime('%Y%m%d-%H%M')
72+my_dest = time.strftime(f'{backup_prefix}{timestamp_str}')
6173
6274 cmd = ["rsync", "--human-readable", "-a", "--hard-links",
6375 "--delete", "--compress-level", "9",
6476 "-e", "ssh"
6577 ]
6678
67-if not args.quiet:
68- cmd.extend(["-v", "--progress"])
6979
80+cmd = rsync_quietness(cmd)
7081 cmd.extend(args.rsync_opt)
7182 cmd.extend(link_dest_args)
7283
@@ -75,4 +86,26 @@
7586
7687 if not args.quiet:
7788 print(*cmd)
78-os.execvp(cmd[0], cmd)
89+subprocess.run(cmd, check=False) # don't let permissions problems get in the way
90+
91+with tempfile.NamedTemporaryFile(prefix="rsnappush-perms.") as permissions_file:
92+ compressed_perms_file = lzma.open(permissions_file.name, mode="w")
93+
94+ get_perms_cmd = ["getfacl", "-R", "--absolute-names", args.source]
95+
96+ with subprocess.Popen(get_perms_cmd, stdout=subprocess.PIPE) as proc:
97+ shutil.copyfileobj(proc.stdout, compressed_perms_file)
98+
99+ compressed_perms_file.close()
100+
101+ mkdir_cmd = ssh_prefix(["mkdir", "-p", os.path.join(dest_path, "permissions")])
102+ subprocess.run(mkdir_cmd)
103+ perms_rsync = ["rsync", "--human-readable", "-a", "-e", "ssh"]
104+ perms_rsync = rsync_quietness(perms_rsync)
105+ perms_rsync.extend(args.rsync_opt)
106+
107+ perms_rsync.extend([permissions_file.name,
108+ os.path.join(args.dest, 'permissions', f'permissions-{timestamp_str}.xz')])
109+ if not args.quiet:
110+ print(*perms_rsync)
111+ subprocess.run(perms_rsync, check=True)