dar-backup 0.6.5__py3-none-any.whl → 0.6.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dar_backup/__about__.py +1 -1
- dar_backup/cleanup.py +70 -24
- dar_backup/dar_backup.py +19 -9
- dar_backup/manager.py +37 -18
- {dar_backup-0.6.5.dist-info → dar_backup-0.6.7.dist-info}/METADATA +20 -5
- dar_backup-0.6.7.dist-info/RECORD +13 -0
- dar_backup-0.6.5.dist-info/RECORD +0 -13
- {dar_backup-0.6.5.dist-info → dar_backup-0.6.7.dist-info}/WHEEL +0 -0
- {dar_backup-0.6.5.dist-info → dar_backup-0.6.7.dist-info}/entry_points.txt +0 -0
- {dar_backup-0.6.5.dist-info → dar_backup-0.6.7.dist-info}/licenses/LICENSE +0 -0
dar_backup/__about__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.6.
|
|
1
|
+
__version__ = "0.6.7"
|
dar_backup/cleanup.py
CHANGED
|
@@ -22,17 +22,22 @@ import sys
|
|
|
22
22
|
|
|
23
23
|
from datetime import datetime, timedelta
|
|
24
24
|
from time import time
|
|
25
|
+
from typing import Dict, List, NamedTuple
|
|
25
26
|
|
|
26
27
|
from . import __about__ as about
|
|
27
28
|
from dar_backup.config_settings import ConfigSettings
|
|
28
29
|
from dar_backup.util import extract_error_lines
|
|
29
30
|
from dar_backup.util import list_backups
|
|
31
|
+
from dar_backup.util import run_command
|
|
30
32
|
from dar_backup.util import setup_logging
|
|
31
33
|
|
|
34
|
+
from dar_backup.util import CommandResult
|
|
35
|
+
|
|
36
|
+
|
|
32
37
|
|
|
33
38
|
logger = None
|
|
34
39
|
|
|
35
|
-
def delete_old_backups(backup_dir, age, backup_type, backup_definition=None):
|
|
40
|
+
def delete_old_backups(backup_dir, age, backup_type, args, backup_definition=None):
|
|
36
41
|
"""
|
|
37
42
|
Delete backups older than the specified age in days.
|
|
38
43
|
Only .dar and .par2 files are considered for deletion.
|
|
@@ -46,6 +51,8 @@ def delete_old_backups(backup_dir, age, backup_type, backup_definition=None):
|
|
|
46
51
|
now = datetime.now()
|
|
47
52
|
cutoff_date = now - timedelta(days=age)
|
|
48
53
|
|
|
54
|
+
archives_deleted = {}
|
|
55
|
+
|
|
49
56
|
for filename in sorted(os.listdir(backup_dir)):
|
|
50
57
|
if not (filename.endswith('.dar') or filename.endswith('.par2')):
|
|
51
58
|
continue
|
|
@@ -64,11 +71,18 @@ def delete_old_backups(backup_dir, age, backup_type, backup_definition=None):
|
|
|
64
71
|
try:
|
|
65
72
|
os.remove(file_path)
|
|
66
73
|
logger.info(f"Deleted {backup_type} backup: {file_path}")
|
|
74
|
+
archive_name = filename.split('.')[0]
|
|
75
|
+
if not archive_name in archives_deleted:
|
|
76
|
+
logger.debug(f"Archive name: '{archive_name}' added to catalog deletion list")
|
|
77
|
+
archives_deleted[archive_name] = True
|
|
67
78
|
except Exception as e:
|
|
68
79
|
logger.error(f"Error deleting file {file_path}: {e}")
|
|
69
80
|
|
|
81
|
+
for archive_name in archives_deleted.keys():
|
|
82
|
+
delete_catalog(archive_name, args)
|
|
83
|
+
|
|
70
84
|
|
|
71
|
-
def delete_archive(backup_dir, archive_name):
|
|
85
|
+
def delete_archive(backup_dir, archive_name, args):
|
|
72
86
|
"""
|
|
73
87
|
Delete all .dar and .par2 files in the backup directory for the given archive name.
|
|
74
88
|
|
|
@@ -90,7 +104,9 @@ def delete_archive(backup_dir, archive_name):
|
|
|
90
104
|
except Exception as e:
|
|
91
105
|
logger.error(f"Error deleting archive slice {file_path}: {e}")
|
|
92
106
|
|
|
93
|
-
if
|
|
107
|
+
if files_deleted:
|
|
108
|
+
delete_catalog(archive_name, args)
|
|
109
|
+
else:
|
|
94
110
|
logger.info("No .dar files matched the regex for deletion.")
|
|
95
111
|
|
|
96
112
|
# Delete associated .par2 files
|
|
@@ -110,6 +126,29 @@ def delete_archive(backup_dir, archive_name):
|
|
|
110
126
|
logger.info("No .par2 matched the regex for deletion.")
|
|
111
127
|
|
|
112
128
|
|
|
129
|
+
def delete_catalog(catalog_name: str, args: NamedTuple) -> bool:
|
|
130
|
+
"""
|
|
131
|
+
Call `manager.py` to delete the specified catalog in it's database
|
|
132
|
+
"""
|
|
133
|
+
command = [f"manager", "--remove-specific-archive", catalog_name, "--config-file", args.config_file, '--log-level', 'debug', '--log-stdout']
|
|
134
|
+
logger.info(f"Deleting catalog '{catalog_name}' using config file: '{args.config_file}'")
|
|
135
|
+
try:
|
|
136
|
+
result:CommandResult = run_command(command)
|
|
137
|
+
if result.returncode == 0:
|
|
138
|
+
logger.info(f"Deleted catalog '{catalog_name}', using config file: '{args.config_file}'")
|
|
139
|
+
logger.debug(f"Stdout: manager.py --remove-specific-archive output:\n{result.stdout}")
|
|
140
|
+
return True
|
|
141
|
+
elif result.returncode == 2:
|
|
142
|
+
logger.warning(f"catalog '{catalog_name}' not found in the database, skipping deletion")
|
|
143
|
+
return True
|
|
144
|
+
else:
|
|
145
|
+
logger.error(f"Error deleting catalog {catalog_name}: {result.stderr}")
|
|
146
|
+
return False
|
|
147
|
+
except Exception as e:
|
|
148
|
+
logger.error(f"Error deleting catalog {catalog_name}: {e}")
|
|
149
|
+
return False
|
|
150
|
+
|
|
151
|
+
|
|
113
152
|
def show_version():
|
|
114
153
|
script_name = os.path.basename(sys.argv[0])
|
|
115
154
|
print(f"{script_name} {about.__version__}")
|
|
@@ -118,8 +157,6 @@ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW,
|
|
|
118
157
|
See section 15 and section 16 in the supplied "LICENSE" file.''')
|
|
119
158
|
|
|
120
159
|
def main():
|
|
121
|
-
|
|
122
|
-
|
|
123
160
|
global logger
|
|
124
161
|
|
|
125
162
|
parser = argparse.ArgumentParser(description="Cleanup old archives according to AGE configuration.")
|
|
@@ -127,9 +164,11 @@ def main():
|
|
|
127
164
|
parser.add_argument('-c', '--config-file', '-c', type=str, help="Path to 'dar-backup.conf'", default='~/.config/dar-backup/dar-backup.conf')
|
|
128
165
|
parser.add_argument('-v', '--version', action='store_true', help="Show version information.")
|
|
129
166
|
parser.add_argument('--alternate-archive-dir', type=str, help="Cleanup in this directory instead of the default one.")
|
|
130
|
-
parser.add_argument('--cleanup-specific-
|
|
167
|
+
parser.add_argument('--cleanup-specific-archives', type=str, help="Commas separated list of archives to cleanup")
|
|
131
168
|
parser.add_argument('-l', '--list', action='store_true', help="List available archives.")
|
|
132
169
|
parser.add_argument('--verbose', action='store_true', help="Print various status messages to screen")
|
|
170
|
+
parser.add_argument('--log-level', type=str, help="`debug` or `trace`, default is `info`", default="info")
|
|
171
|
+
parser.add_argument('--log-stdout', action='store_true', help='also print log messages to stdout')
|
|
133
172
|
args = parser.parse_args()
|
|
134
173
|
|
|
135
174
|
args.config_file = os.path.expanduser(args.config_file)
|
|
@@ -142,7 +181,8 @@ def main():
|
|
|
142
181
|
config_settings = ConfigSettings(args.config_file)
|
|
143
182
|
|
|
144
183
|
start_time=int(time())
|
|
145
|
-
logger = setup_logging(config_settings.logfile_location,
|
|
184
|
+
logger = setup_logging(config_settings.logfile_location, args.log_level, args.log_stdout)
|
|
185
|
+
|
|
146
186
|
logger.info(f"=====================================")
|
|
147
187
|
logger.info(f"cleanup.py started, version: {about.__version__}")
|
|
148
188
|
|
|
@@ -156,7 +196,7 @@ def main():
|
|
|
156
196
|
args.verbose and (print(f"Backup dir: {config_settings.backup_dir}"))
|
|
157
197
|
args.verbose and (print(f"Logfile location: {config_settings.logfile_location}"))
|
|
158
198
|
args.verbose and (print(f"--alternate-archive-dir: {args.alternate_archive_dir}"))
|
|
159
|
-
args.verbose and (print(f"--cleanup-specific-
|
|
199
|
+
args.verbose and (print(f"--cleanup-specific-archives:{args.cleanup_specific_archives}"))
|
|
160
200
|
|
|
161
201
|
# run PREREQ scripts
|
|
162
202
|
if 'PREREQ' in config_settings.config:
|
|
@@ -175,15 +215,21 @@ def main():
|
|
|
175
215
|
|
|
176
216
|
|
|
177
217
|
if args.alternate_archive_dir:
|
|
218
|
+
if not os.path.exists(args.alternate_archive_dir):
|
|
219
|
+
logger.error(f"Alternate archive directory does not exist: {args.alternate_archive_dir}, exiting")
|
|
220
|
+
sys.exit(1)
|
|
221
|
+
if not os.path.isdir(args.alternate_archive_dir):
|
|
222
|
+
logger.error(f"Alternate archive directory is not a directory, exiting")
|
|
223
|
+
sys.exit(1)
|
|
178
224
|
config_settings.backup_dir = args.alternate_archive_dir
|
|
179
225
|
|
|
180
226
|
|
|
181
|
-
if args.
|
|
182
|
-
|
|
183
|
-
archive_names = args.
|
|
227
|
+
if args.cleanup_specific_archives:
|
|
228
|
+
logger.info(f"Cleaning up specific archives: {args.cleanup_specific_archives}")
|
|
229
|
+
archive_names = args.cleanup_specific_archives.split(',')
|
|
184
230
|
for archive_name in archive_names:
|
|
185
|
-
|
|
186
|
-
delete_archive(config_settings.backup_dir, archive_name.strip())
|
|
231
|
+
logger.info(f"Deleting archive: {archive_name}")
|
|
232
|
+
delete_archive(config_settings.backup_dir, archive_name.strip(), args)
|
|
187
233
|
elif args.list:
|
|
188
234
|
list_backups(config_settings.backup_dir, args.backup_definition)
|
|
189
235
|
else:
|
|
@@ -196,22 +242,22 @@ def main():
|
|
|
196
242
|
backup_definitions.append(file.split('.')[0])
|
|
197
243
|
|
|
198
244
|
for definition in backup_definitions:
|
|
199
|
-
delete_old_backups(config_settings.backup_dir, config_settings.diff_age, 'DIFF', definition)
|
|
200
|
-
delete_old_backups(config_settings.backup_dir, config_settings.incr_age, 'INCR', definition)
|
|
245
|
+
delete_old_backups(config_settings.backup_dir, config_settings.diff_age, 'DIFF', args, definition)
|
|
246
|
+
delete_old_backups(config_settings.backup_dir, config_settings.incr_age, 'INCR', args, definition)
|
|
201
247
|
|
|
202
248
|
|
|
203
249
|
end_time=int(time())
|
|
204
250
|
logger.info(f"END TIME: {end_time}")
|
|
205
251
|
|
|
206
|
-
error_lines = extract_error_lines(config_settings.logfile_location, start_time, end_time)
|
|
207
|
-
if len(error_lines) > 0:
|
|
208
|
-
args.verbose and print("\033[1m\033[31mErrors\033[0m encountered")
|
|
209
|
-
for line in error_lines:
|
|
210
|
-
args.verbose and print(line)
|
|
211
|
-
sys.exit(1)
|
|
212
|
-
else:
|
|
213
|
-
args.verbose and print("\033[1m\033[32mSUCCESS\033[0m No errors encountered")
|
|
214
|
-
sys.exit(0)
|
|
252
|
+
# error_lines = extract_error_lines(config_settings.logfile_location, start_time, end_time)
|
|
253
|
+
# if len(error_lines) > 0:
|
|
254
|
+
# args.verbose and print("\033[1m\033[31mErrors\033[0m encountered")
|
|
255
|
+
# for line in error_lines:
|
|
256
|
+
# args.verbose and print(line)
|
|
257
|
+
# sys.exit(1)
|
|
258
|
+
# else:
|
|
259
|
+
# args.verbose and print("\033[1m\033[32mSUCCESS\033[0m No errors encountered")
|
|
260
|
+
# sys.exit(0)
|
|
215
261
|
|
|
216
262
|
if __name__ == "__main__":
|
|
217
263
|
main()
|
dar_backup/dar_backup.py
CHANGED
|
@@ -30,7 +30,7 @@ from dar_backup.util import RestoreError
|
|
|
30
30
|
|
|
31
31
|
logger = None
|
|
32
32
|
|
|
33
|
-
def generic_backup(type: str, command: List[str], backup_file: str, backup_definition: str, darrc: str, config_settings: ConfigSettings):
|
|
33
|
+
def generic_backup(type: str, command: List[str], backup_file: str, backup_definition: str, darrc: str, config_settings: ConfigSettings, args: argparse.Namespace):
|
|
34
34
|
"""
|
|
35
35
|
Performs a backup using the 'dar' command.
|
|
36
36
|
|
|
@@ -64,6 +64,15 @@ def generic_backup(type: str, command: List[str], backup_file: str, backup_defin
|
|
|
64
64
|
logger.warning("Backup completed with some files not backed up, this can happen if files are changed/deleted during the backup.")
|
|
65
65
|
else:
|
|
66
66
|
raise Exception(str(process))
|
|
67
|
+
|
|
68
|
+
if process.returncode == 0 or process.returncode == 5:
|
|
69
|
+
add_catalog_command = ['manager', '--add-specific-archive' ,backup_file, '--config-file', args.config_file, '--log-level', "debug", "--log-stdout"]
|
|
70
|
+
command_result = run_command(add_catalog_command, config_settings.command_timeout_secs)
|
|
71
|
+
if command_result.returncode == 0:
|
|
72
|
+
logger.info(f"Catalog for archive '{backup_file}' added successfully to its manager.")
|
|
73
|
+
else:
|
|
74
|
+
logger.error(f"Catalog for archive '{backup_file}' not added.")
|
|
75
|
+
|
|
67
76
|
except subprocess.CalledProcessError as e:
|
|
68
77
|
logger.error(f"Backup command failed: {e}")
|
|
69
78
|
raise BackupError(f"Backup command failed: {e}") from e
|
|
@@ -409,19 +418,22 @@ def perform_backup(args: argparse.Namespace, config_settings: ConfigSettings, ba
|
|
|
409
418
|
command = create_backup_command(backup_type, backup_file, args.darrc, backup_definition_path, latest_base_backup)
|
|
410
419
|
|
|
411
420
|
# Perform backup
|
|
412
|
-
generic_backup(backup_type, command, backup_file, backup_definition_path, args.darrc, config_settings)
|
|
421
|
+
generic_backup(backup_type, command, backup_file, backup_definition_path, args.darrc, config_settings, args)
|
|
413
422
|
|
|
414
423
|
logger.info("Starting verification...")
|
|
415
|
-
|
|
416
|
-
if
|
|
424
|
+
verify_result = verify(args, backup_file, backup_definition_path, config_settings)
|
|
425
|
+
if verify_result:
|
|
417
426
|
logger.info("Verification completed successfully.")
|
|
418
427
|
else:
|
|
419
428
|
logger.error("Verification failed.")
|
|
420
429
|
|
|
421
|
-
|
|
430
|
+
|
|
431
|
+
if verify_result and config_settings.par2_enabled:
|
|
422
432
|
logger.info("Generate par2 redundancy files.")
|
|
423
433
|
generate_par2_files(backup_file, config_settings, args)
|
|
424
434
|
logger.info("par2 files completed successfully.")
|
|
435
|
+
|
|
436
|
+
|
|
425
437
|
except Exception as e:
|
|
426
438
|
logger.exception(f"Error during {backup_type} backup process, continuing to next backup definition.")
|
|
427
439
|
|
|
@@ -461,16 +473,14 @@ def generate_par2_files(backup_file: str, config_settings: ConfigSettings, args)
|
|
|
461
473
|
for slice_file in dar_slices:
|
|
462
474
|
file_path = os.path.join(config_settings.backup_dir, slice_file)
|
|
463
475
|
|
|
464
|
-
|
|
465
|
-
logger.info(f"{counter}/{number_of_slices}: Now generating par2 files for {file_path}")
|
|
476
|
+
logger.info(f"{counter}/{number_of_slices}: Now generating par2 files for {file_path}")
|
|
466
477
|
|
|
467
478
|
# Run the par2 command to generate redundancy files with error correction
|
|
468
479
|
command = ['par2', 'create', f'-r{config_settings.error_correction_percent}', '-q', '-q', file_path]
|
|
469
480
|
process = run_command(command, config_settings.command_timeout_secs)
|
|
470
481
|
|
|
471
482
|
if process.returncode == 0:
|
|
472
|
-
|
|
473
|
-
logger.info(f"{counter}/{number_of_slices}: Done")
|
|
483
|
+
logger.info(f"{counter}/{number_of_slices}: Done")
|
|
474
484
|
else:
|
|
475
485
|
logger.error(f"Error generating par2 files for {file_path}")
|
|
476
486
|
raise subprocess.CalledProcessError(process.returncode, command)
|
dar_backup/manager.py
CHANGED
|
@@ -31,6 +31,8 @@ from . import __about__ as about
|
|
|
31
31
|
from dar_backup.config_settings import ConfigSettings
|
|
32
32
|
from dar_backup.util import run_command
|
|
33
33
|
from dar_backup.util import setup_logging
|
|
34
|
+
from dar_backup.util import CommandResult
|
|
35
|
+
|
|
34
36
|
from datetime import datetime
|
|
35
37
|
from time import time
|
|
36
38
|
from typing import Dict, List, NamedTuple
|
|
@@ -60,6 +62,7 @@ def create_db(backup_def: str, config_settings: ConfigSettings):
|
|
|
60
62
|
|
|
61
63
|
if os.path.exists(database_path):
|
|
62
64
|
logger.warning(f'"{database_path}" already exists, skipping creation')
|
|
65
|
+
return 0
|
|
63
66
|
else:
|
|
64
67
|
logger.info(f'Create catalog database: "{database_path}"')
|
|
65
68
|
command = ['dar_manager', '--create' , database_path]
|
|
@@ -90,8 +93,16 @@ def list_catalogs(backup_def: str, config_settings: ConfigSettings) -> NamedTupl
|
|
|
90
93
|
database = f"{backup_def}{DB_SUFFIX}"
|
|
91
94
|
database_path = os.path.join(config_settings.backup_dir, database)
|
|
92
95
|
if not os.path.exists(database_path):
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
error_msg = f'Database not found: "{database_path}"'
|
|
97
|
+
logger.error(error_msg)
|
|
98
|
+
commandResult = CommandResult(
|
|
99
|
+
process=None,
|
|
100
|
+
stdout='',
|
|
101
|
+
stderr=error_msg,
|
|
102
|
+
returncode=1,
|
|
103
|
+
timeout=1,
|
|
104
|
+
command=[])
|
|
105
|
+
return commandResult
|
|
95
106
|
command = ['dar_manager', '--base', database_path, '--list']
|
|
96
107
|
process = run_command(command)
|
|
97
108
|
stdout, stderr = process.stdout, process.stderr
|
|
@@ -277,32 +288,44 @@ def backup_def_from_archive(archive: str) -> str:
|
|
|
277
288
|
"""
|
|
278
289
|
return the backup definition from archive name
|
|
279
290
|
"""
|
|
291
|
+
logger.debug(f"Get backup definition from archive: '{archive}'")
|
|
280
292
|
search = re.search("(.*?)_", archive)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
293
|
+
if search:
|
|
294
|
+
backup_def = search.group(1)
|
|
295
|
+
logger.debug(f"backup definition: '{backup_def}' from given archive '{archive}'")
|
|
296
|
+
return backup_def
|
|
297
|
+
logger.error(f"Could not find backup definition from archive name: '{archive}'")
|
|
298
|
+
return None
|
|
284
299
|
|
|
285
300
|
|
|
286
301
|
|
|
287
302
|
def remove_specific_archive(archive: str, config_settings: ConfigSettings) -> int:
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
- 0 if the archive was removed from it's catalog
|
|
307
|
+
- 1 if there was an error removing the archive
|
|
308
|
+
- 2 if the archive was not found in the catalog
|
|
309
|
+
|
|
310
|
+
"""
|
|
288
311
|
backup_def = backup_def_from_archive(archive)
|
|
289
312
|
database_path = os.path.join(config_settings.backup_dir, f"{backup_def}{DB_SUFFIX}")
|
|
290
313
|
cat_no = cat_no_for_name(archive, config_settings)
|
|
291
314
|
if cat_no >= 0:
|
|
292
315
|
command = ['dar_manager', '--base', database_path, "--delete", str(cat_no)]
|
|
293
|
-
process = run_command(command)
|
|
316
|
+
process: CommandResult = run_command(command)
|
|
317
|
+
logger.info(f"CommandResult: {process}")
|
|
294
318
|
else:
|
|
295
|
-
logger.
|
|
296
|
-
return
|
|
319
|
+
logger.warning(f"archive: '{archive}' not found in it's catalog database: {database_path}")
|
|
320
|
+
return 2
|
|
297
321
|
|
|
298
322
|
if process.returncode == 0:
|
|
299
323
|
logger.info(f"'{archive}' removed from it's catalog")
|
|
324
|
+
return 0
|
|
300
325
|
else:
|
|
301
326
|
logger.error(process.stdout)
|
|
302
327
|
logger.error(process.sterr)
|
|
303
|
-
|
|
304
|
-
return process.returncode
|
|
305
|
-
|
|
328
|
+
return 1
|
|
306
329
|
|
|
307
330
|
|
|
308
331
|
|
|
@@ -322,7 +345,7 @@ def main():
|
|
|
322
345
|
parser.add_argument('-d', '--backup-def', type=str, help='Restrict to work only on this backup definition')
|
|
323
346
|
parser.add_argument('--add-specific-archive', type=str, help='Add this archive to catalog database')
|
|
324
347
|
parser.add_argument('--remove-specific-archive', type=str, help='Remove this archive from catalog database')
|
|
325
|
-
parser.add_argument('--list-
|
|
348
|
+
parser.add_argument('-l', '--list-catalogs', action='store_true', help='List catalogs in databases for all backup definitions')
|
|
326
349
|
parser.add_argument('--list-catalog-contents', type=int, help="List contents of a catalog. Argument is the 'archive #', '-d <definition>' argument is also required")
|
|
327
350
|
parser.add_argument('--find-file', type=str, help="List catalogs containing <path>/file. '-d <definition>' argument is also required")
|
|
328
351
|
parser.add_argument('--verbose', action='store_true', help='Be more verbose')
|
|
@@ -430,15 +453,11 @@ See section 15 and section 16 in the supplied "LICENSE" file.''')
|
|
|
430
453
|
|
|
431
454
|
|
|
432
455
|
if args.remove_specific_archive:
|
|
433
|
-
|
|
434
|
-
if remove_specific_archive(args.remove_specific_archive, config_settings) == 0:
|
|
435
|
-
sys.exit(0)
|
|
436
|
-
else:
|
|
437
|
-
sys.exit(1)
|
|
456
|
+
return remove_specific_archive(args.remove_specific_archive, config_settings)
|
|
438
457
|
|
|
439
458
|
|
|
440
459
|
|
|
441
|
-
if args.
|
|
460
|
+
if args.list_catalogs:
|
|
442
461
|
if args.backup_def:
|
|
443
462
|
process = list_catalogs(args.backup_def, config_settings)
|
|
444
463
|
result = process.returncode
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dar-backup
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary: A script to do full, differential and incremental backups using dar. Some files are restored from the backups during verification, after which par2 redundancy files are created. The script also has a cleanup feature to remove old backups and par2 files.
|
|
5
|
-
Project-URL: Homepage, https://github.com/per2jensen/dar-backup
|
|
5
|
+
Project-URL: Homepage, https://github.com/per2jensen/dar-backup/tree/main/v2
|
|
6
6
|
Project-URL: Changelog, https://github.com/per2jensen/dar-backup/blob/main/v2/Changelog.md
|
|
7
7
|
Project-URL: Issues, https://github.com/per2jensen/dar-backup/issues
|
|
8
8
|
Author-email: dar-backup <per2jensen@gmail.com>
|
|
@@ -845,6 +845,7 @@ Example of backup definition for a home directory
|
|
|
845
845
|
Installation is currently in a venv. These commands are installed in the venv:
|
|
846
846
|
- dar-back
|
|
847
847
|
- cleanup
|
|
848
|
+
- manager
|
|
848
849
|
|
|
849
850
|
To install, create a venv and run pip:
|
|
850
851
|
````
|
|
@@ -911,22 +912,36 @@ options:
|
|
|
911
912
|
--log-stdout also print log messages to stdout
|
|
912
913
|
--do-not-compare do not compare restores to file system
|
|
913
914
|
-v, --version Show version and license information.
|
|
914
|
-
|
|
915
915
|
````
|
|
916
916
|
|
|
917
917
|
## 4
|
|
918
|
+
Generate the archive catalog database(s).
|
|
919
|
+
`dar-backup` expects the catalog databases to be in place, it does not automatically create them (by design)
|
|
920
|
+
|
|
921
|
+
````
|
|
922
|
+
manager --create-db --config-file <path to config file> --log-level debug --log-stdout
|
|
923
|
+
````
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
## 5
|
|
918
929
|
You are ready to do backups of all your backup definitions, if your backup definitions are
|
|
919
930
|
in place in BACKUP.D_DIR (see config file)
|
|
920
931
|
````
|
|
921
932
|
dar-backup --full-backup
|
|
922
933
|
````
|
|
934
|
+
If you want to see dar-backup's log entries in the terminal, use the `--log-stdout` option. This is also useful if dar-backup is started by systemd.
|
|
935
|
+
|
|
936
|
+
If you want more log messages, use the `--log-level debug` option.
|
|
937
|
+
|
|
923
938
|
|
|
924
|
-
|
|
939
|
+
If you want a backup of a single definition, use the `-d <backup definition>` option. The definition's name is the filename of the definition in the `backup.d` config directory.
|
|
925
940
|
````
|
|
926
941
|
dar-backup --full-backup -d <your backup definition>
|
|
927
942
|
````
|
|
928
943
|
|
|
929
|
-
##
|
|
944
|
+
## 6
|
|
930
945
|
|
|
931
946
|
Deactivate the virtual environment
|
|
932
947
|
````
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
dar_backup/.darrc,sha256=3d9opAnnZGU9XLyQpTDsLtgo6hqsvZ3JU-yMLz-7_f0,2110
|
|
2
|
+
dar_backup/__about__.py,sha256=0ouks3vBIBYQpXQLGG2c_DveClXKjoOTb3ZY9LRV9Xw,21
|
|
3
|
+
dar_backup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
dar_backup/cleanup.py,sha256=9yEdRR84XPtEvBGc2QfwGBQl2tdTPttjetHeiSc_TsM,11419
|
|
5
|
+
dar_backup/config_settings.py,sha256=CBMUhLOOZ-x7CRdS3vBDk4TYaGqC4N1Ot8IMH-qPaI0,3617
|
|
6
|
+
dar_backup/dar_backup.py,sha256=oUlGCLeYwkJKSqn1qzKqkhpoQVTp-fCWyJcpmkSnLjc,32703
|
|
7
|
+
dar_backup/manager.py,sha256=S66gC6m-xaMMZR3MtaB0VGYEaGPohAO0DNMSSXvimM4,19869
|
|
8
|
+
dar_backup/util.py,sha256=SSSJYM9lQZfubhTUBlX1xDGWmCpYEF3ePARmlY544xM,11283
|
|
9
|
+
dar_backup-0.6.7.dist-info/METADATA,sha256=QB3M9KzbnyRUhRBbljmYFN5rYEhvzVBB2EbOD6QWsTs,64452
|
|
10
|
+
dar_backup-0.6.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
+
dar_backup-0.6.7.dist-info/entry_points.txt,sha256=x9vnW-JEl8mpDJC69f_XBcn0mBSkV1U0cyvFV-NAP1g,126
|
|
12
|
+
dar_backup-0.6.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
13
|
+
dar_backup-0.6.7.dist-info/RECORD,,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
dar_backup/.darrc,sha256=3d9opAnnZGU9XLyQpTDsLtgo6hqsvZ3JU-yMLz-7_f0,2110
|
|
2
|
-
dar_backup/__about__.py,sha256=_f8whmZJ36ZCTk0Zldzy3KONxDBm0bxyKt7pCSHC3cE,21
|
|
3
|
-
dar_backup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
dar_backup/cleanup.py,sha256=DgmxSUwKrLLIQuYSIY_yTRhIuOMgI6ivjlQuH4u3wX4,9057
|
|
5
|
-
dar_backup/config_settings.py,sha256=CBMUhLOOZ-x7CRdS3vBDk4TYaGqC4N1Ot8IMH-qPaI0,3617
|
|
6
|
-
dar_backup/dar_backup.py,sha256=YZoVu9NJX3_WIkQIG8EMLSK3-VWdslI0c2XKrM2Un38,32214
|
|
7
|
-
dar_backup/manager.py,sha256=2qTcn1HiDrejc6S7dLpkylURGzMQ0QqTaSl2KQQ58Uw,19198
|
|
8
|
-
dar_backup/util.py,sha256=SSSJYM9lQZfubhTUBlX1xDGWmCpYEF3ePARmlY544xM,11283
|
|
9
|
-
dar_backup-0.6.5.dist-info/METADATA,sha256=z0xQGBCg2sGMi93gtNCK0DXINE1ZgsohQbQh0zutlD4,63802
|
|
10
|
-
dar_backup-0.6.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
-
dar_backup-0.6.5.dist-info/entry_points.txt,sha256=x9vnW-JEl8mpDJC69f_XBcn0mBSkV1U0cyvFV-NAP1g,126
|
|
12
|
-
dar_backup-0.6.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
13
|
-
dar_backup-0.6.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|