backup: capture borg output for later reporting
This commit is contained in:
parent
0c74f1676c
commit
59ad2b5b4d
38
backup.py
38
backup.py
|
@ -10,7 +10,9 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import stat
|
import stat
|
||||||
import time
|
import time
|
||||||
|
import select
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import threading
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import typing
|
import typing
|
||||||
|
@ -245,13 +247,17 @@ def main(argv: list[str]):
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
config = Config(args.config)
|
config = Config(args.config)
|
||||||
|
|
||||||
|
# Run backup
|
||||||
backup = Backup(config, args.dry_run)
|
backup = Backup(config, args.dry_run)
|
||||||
|
captured_output: list[bytes] = []
|
||||||
|
|
||||||
if args.dry_run:
|
if args.dry_run:
|
||||||
if args.debug:
|
if args.debug:
|
||||||
backup.run(sys.stdout.buffer)
|
backup.run(sys.stdout.buffer)
|
||||||
else:
|
else:
|
||||||
with open(os.devnull, "wb") as out:
|
with open(os.devnull, "wb") as out:
|
||||||
backup.run(out)
|
backup.run(out)
|
||||||
|
sys.stdout.flush()
|
||||||
else:
|
else:
|
||||||
borg = subprocess.Popen([args.borg,
|
borg = subprocess.Popen([args.borg,
|
||||||
"create",
|
"create",
|
||||||
|
@ -264,12 +270,33 @@ def main(argv: list[str]):
|
||||||
"--paths-from-stdin",
|
"--paths-from-stdin",
|
||||||
"--paths-delimiter", "\\0",
|
"--paths-delimiter", "\\0",
|
||||||
"::'{hostname}-{now:%Y%m%d-%H%M%S}'"],
|
"::'{hostname}-{now:%Y%m%d-%H%M%S}'"],
|
||||||
stdin=subprocess.PIPE)
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT)
|
||||||
if borg.stdin is None:
|
if borg.stdin is None:
|
||||||
raise Exception("no pipe")
|
raise Exception("no pipe")
|
||||||
|
|
||||||
|
# Use a thread to capture output
|
||||||
|
def reader_thread(fh):
|
||||||
|
os.set_blocking(fh.fileno(), False)
|
||||||
|
while True:
|
||||||
|
ready = select.select([fh.fileno()], [], [])
|
||||||
|
if not len(ready[0]):
|
||||||
|
break
|
||||||
|
data = fh.read(8192)
|
||||||
|
if not len(data):
|
||||||
|
break
|
||||||
|
sys.stdout.buffer.write(data)
|
||||||
|
sys.stdout.flush()
|
||||||
|
captured_output.append(data)
|
||||||
|
fh.close()
|
||||||
|
reader = threading.Thread(target=reader_thread, args=(borg.stdout,))
|
||||||
|
reader.daemon = True
|
||||||
|
reader.start()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Give borg some time to start, just to clean up stdout
|
# Give borg some time to start, just to clean up stdout
|
||||||
time.sleep(2)
|
time.sleep(1)
|
||||||
backup.run(borg.stdin)
|
backup.run(borg.stdin)
|
||||||
except BrokenPipeError:
|
except BrokenPipeError:
|
||||||
sys.stderr.write(f"broken pipe\n")
|
sys.stderr.write(f"broken pipe\n")
|
||||||
|
@ -279,13 +306,12 @@ def main(argv: list[str]):
|
||||||
except BrokenPipeError:
|
except BrokenPipeError:
|
||||||
pass
|
pass
|
||||||
borg.wait()
|
borg.wait()
|
||||||
|
reader.join()
|
||||||
ret = borg.returncode
|
ret = borg.returncode
|
||||||
if ret < 0:
|
if ret < 0:
|
||||||
sys.stderr.write(f"error: process exited with signal {-ret}\n")
|
backup.log('E', f"borg exited with signal {-ret}")
|
||||||
return 1
|
|
||||||
elif ret != 0:
|
elif ret != 0:
|
||||||
sys.stderr.write(f"error: process exited with return code {ret}\n")
|
backup.log('E', f"borg exited with return code {ret}")
|
||||||
return ret
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user