From e8d9ee8d8b7f7fbd133aca082ce77825768ff71c Mon Sep 17 00:00:00 2001 From: myitinos Date: Mon, 22 Jul 2019 18:15:13 +0800 Subject: [PATCH] v1.0 (need testing) --- clone.py | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 clone.py diff --git a/clone.py b/clone.py new file mode 100644 index 0000000..c7b4fe4 --- /dev/null +++ b/clone.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 + +import os +import logging +import string +import hashlib +import time + + +class Cloner: + def __init__(self, targetDir: str, backupDir: str): + self.targetDir = targetDir + self.backupDir = backupDir + self.interval = 1 + + def handleDir(self, dirPath: str): + backupDirPath = dirPath.replace(self.targetDir, self.backupDir) + if not os.path.isdir(backupDirPath): + os.system('mkdir {path}'.format(path=backupDirPath)) + with os.scandir(dirPath) as it: + for entry in it: + if entry.is_dir(): + self.handleDir(entry.path) + elif entry.is_file(): + self.handleFile(entry.path) + + def handleFile(self, fileName: str): + cloneFileName = fileName.replace(self.targetDir, self.backupDir) + + if os.path.exists(cloneFileName): + with open(cloneFileName + '.md5', 'r') as cloneHashFile, open(fileName, 'rb') as targetFile: + cloneHashFileContent = cloneHashFile.read() + targetFileContent = targetFile.read() + realHash = hashlib.md5(targetFileContent).hexdigest() + if realHash != cloneHashFileContent: + os.system('cp {backup} {real}'.format( + backup=cloneFileName, real=fileName)) + logging.warning( + '{file} failed check, restoring...'.format(file=fileName)) + else: + logging.info('{file} is fine'.format(file=fileName)) + else: + logging.warning( + '{file} is a new file, added to backup dir'.format(file=fileName)) + os.system('cp {real} {clone}'.format( + real=fileName, clone=cloneFileName)) + with open(cloneFileName + '.md5', 'w') as cloneHashFile, open(fileName, 'rb') as targetFile: + targetFileContent = targetFile.read() + cloneHashFile.write(hashlib.md5(targetFileContent).hexdigest()) + + def setLog(self, logFileName: str): + logFormatter = logging.Formatter( + fmt="[%(asctime)s][%(levelname)s] %(message)s", + datefmt='%d-%b-%y %H:%M:%S') + + rootLogger = logging.getLogger() + + fileHandler = logging.FileHandler(logFileName, mode='a') + fileHandler.setFormatter(logFormatter) + rootLogger.addHandler(fileHandler) + + # # uncomment this to enable console logging + # consoleHandler = logging.StreamHandler() + # consoleHandler.setFormatter(logFormatter) + # rootLogger.addHandler(consoleHandler) + + rootLogger.setLevel(logging.WARNING) + + def setInterval(self, interval: int): + self.interval = interval + + def start(self): + while True: + self.handleDir(self.targetDir) + time.sleep(5) + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument( + '--target', + metavar='PATH', + type=str, + required=True, + help='directory to clone and monitor') + parser.add_argument( + '--backup', + metavar='PATH', + type=str, + required=True, + help='backup directory to store clone' + ) + parser.add_argument( + '--interval', + metavar='SECOND', + type=int, + default=1, + help='interval in second(s) which the scripts run, default is 1' + ) + parser.add_argument( + '--log', + metavar='LOGFILE', + type=str, + default='/var/log/py-dir-watcher/log.txt', + help='specify custom logfile target, default is \'/var/log/py-dir-watcher/log.txt\' ' + ) + + args = parser.parse_args() + + app = Cloner(args.target, args.backup) + app.setLog(args.log) + app.setInterval(args.interval) + app.start()