X-Git-Url: https://git.sthu.org/?p=sitarba.git;a=blobdiff_plain;f=shbackup;h=e57e2508500fe22a966357413cb6d398c73a9f20;hp=e97dbf5182790944bfd2eb1c26987d6e8503ae2e;hb=49e5f540ea30ec5a28a98dc560a34cfcace55d2f;hpb=89e63ddff1a18af1f4199e60d8306b8c6da01341 diff --git a/shbackup b/shbackup index e97dbf5..e57e250 100755 --- a/shbackup +++ b/shbackup @@ -1,7 +1,7 @@ #!/usr/bin/python3 """A simple backup solution.""" -__version__ = "0.1" +__version__ = "2.0" __author__ = "Stefan Huber" import datetime @@ -171,8 +171,9 @@ class Config: checksumfn = "checksum" def __init__(self): - self.directory = None - self.format = self.formats[0] + self.backupdir = None + self.format = self.formats[1] + self.tarbin = "/bin/tar" self.excludes = [] self.sets = [] self.checksum = None @@ -181,8 +182,9 @@ class Config: def __repr__(self): - return "[directory: " + self.directory + \ + return "[backupdir: " + self.backupdir + \ ", format: " + self.format + \ + ", tarbin: " + self.tarbin + \ ", excludes: " + repr(self.excludes) + \ ", epochs: " + repr(self.epochs) + \ ", sets: " + repr(self.sets) + "]" @@ -197,23 +199,21 @@ class Config: return realepochs - def _read_destination(self, config, sec): + def _read_global(self, config, sec): for opt in config.options(sec): - if opt=="directory": - self.directory = config.get(sec, opt) - if not os.path.isdir(self.directory): - raise Config.ReadError("Directory '{0}' does not exist.".format(self.directory)) + if opt=="backupdir": + self.backupdir = config.get(sec, opt) + if not os.path.isdir(self.backupdir): + raise Config.ReadError("Backupdir '{0}' does not exist.".format(self.backupdir)) elif opt=="format": self.format = config.get(sec, opt) if not self.format in Config.formats: raise Config.ReadError("Invalid 'format' given.") - else: - raise Config.ReadError("Unknown option '{0}'.".format(opt)) - - - def _read_global(self, config, sec): - for opt in config.options(sec): - if opt.startswith("exclude"): + elif opt=="tarbin": + self.tarbin = config.get(sec, opt) + if not os.path.isfile(self.tarbin): + raise Config.ReadError("Tar binary '{0}' does not exist.".format(self.tarbin)) + elif opt.startswith("exclude"): self.excludes += [ config.get(sec, opt) ] else: raise Config.ReadError("Unknown option '{0}'.".format(opt)) @@ -241,7 +241,7 @@ class Config: if not e.mode in Modes: raise Config.ReadError("Invalid mode '{0}'.".format(e.mode)) - elif opt=="timedelta": + elif opt=="timespan": if name in Epoch.units: raise Config.ReadError("The time delta of a standard epoch " + \ "is not supposed to be redefined. ") @@ -251,7 +251,7 @@ class Config: e.unit = unit e.mult = mult except ValueError as e: - raise Config.ReadError("Invalid timedelta '{0}': {1}".format(td, str(e))) + raise Config.ReadError("Invalid timespan '{0}': {1}".format(td, str(e))) elif opt.startswith("exclude"): e.excludes += [config.get(sec, opt)] @@ -290,16 +290,13 @@ class Config: config = configparser.RawConfigParser() config.read(filename) - for reqsec in ["destination"]: + for reqsec in ["global"]: if not config.has_section(reqsec): raise Config.ReadError("Mandatory section '" + reqsec + "' is missing.") for sec in config.sections(): - if sec=="destination": - self._read_destination(config, sec) - - elif sec=="global": + if sec=="global": self._read_global(config, sec) elif sec.startswith("epoch "): @@ -311,8 +308,8 @@ class Config: else: raise Config.ReadError("Unknown section '" + sec + "'.") - if self.directory == None: - raise Config.ReadError("No destination directory set.") + if self.backupdir == None: + raise Config.ReadError("No backup directory set.") # Compute checksum of config file @@ -325,7 +322,7 @@ class Config: f.close() try: - f = open(os.path.join(self.directory, self.checksumfn), 'r') + f = open(os.path.join(self.backupdir, self.checksumfn), 'r') self.lastchecksum = f.read().strip() f.close() except IOError: @@ -341,10 +338,10 @@ class BackupManager: def listAllDirs(self): - """List all dirs in destination directory""" + """List all dirs in backupdir""" # Get all entries - basedir = self.conf.directory + basedir = self.conf.backupdir dirs = os.listdir(basedir) # Filter directories return [ d for d in dirs if os.path.isdir(os.path.join(basedir, d)) ] @@ -393,9 +390,7 @@ class BackupManager: logfile = logging.getLogger('backuplog') logfile.info("Running file set: " + fileset.name) - tarpath = "/bin/tar" fsfn = os.path.join(targetdir, fileset.name) + "." + self.conf.format - taropts = [] # Add the since date, if given @@ -414,7 +409,7 @@ class BackupManager: taropts += ["-C", "/"] + [ "./" + d.lstrip("/") for d in fileset.dirs] # Launch the tar process - tarargs = [tarpath] + ["-cpvaf", fsfn] + taropts + tarargs = [self.conf.tarbin] + ["-cpvaf", fsfn] + taropts logfile.debug("tar call: " + " ".join(tarargs)) tarp = subprocess.Popen( tarargs, bufsize=-1, \ stdout=subprocess.PIPE, stderr=subprocess.PIPE ) @@ -444,7 +439,8 @@ class BackupManager: if rett != 0: for l in errmsg.decode().split("\n"): logfile.error(l) - logfile.error(tarpath + " returned with exit status " + str(rett) + ".") + logfile.error(self.conf.tarbin + " returned with exit status " + \ + str(rett) + ".") def backup(self, epoch=None, mode=None): @@ -492,8 +488,8 @@ class BackupManager: if yesno == "n": return - # Create new target directory - basedir = self.conf.directory + # Create new backup directory + basedir = self.conf.backupdir dirname = Backup.getDirName(now, epoch, mode) tmpdirname = dirname + ("-%x" % (random.random()*2e16) ) targetdir = os.path.join(basedir, tmpdirname) @@ -567,7 +563,7 @@ class BackupManager: logging.info("No stale/outdated entries to remove.") return - basedir = self.conf.directory + basedir = self.conf.backupdir yesno = self.ask_user_yesno("Remove entries marked by '*'? [y, N] ") if yesno == "y": for d in removeDirs: @@ -600,11 +596,11 @@ def printUsage(): print("") print("Options:") print(" -h, --help print this usage text") - print(" -c, --conf use given configuration file") + print(" -c, --conf FILE use given configuration file") print(" default: /etc/shbackup.conf") - print(" -e, --epoch force to create backup for given epoch:") - print(" year, month, week, day, hour, sporadic") - print(" -m, --mode override mode: full, diff, or incr") + print(" -e, --epoch EPOCH force to create backup for given epoch, which") + print(" can be 'sporadic' or one of the configured epochs") + print(" -m, --mode MODE override mode: full, diff, or incr") print(" -v, --verbose be more verbose and interact with user") print(" --verbosity LEVEL set verbosity to LEVEL, which can be") print(" error, warning, info, debug")