#!/usr/bin/python3 import sys, os, json, re, subprocess CONFIG_DIR = "/etc/BackupPC/pc" PC_DIR = "/var/lib/BackupPC/pc" BIN_DIR = "/usr/share/BackupPC/bin" bpc_ls = os.path.join(BIN_DIR, "BackupPC_ls") bpc_zcat = os.path.join(BIN_DIR, "BackupPC_zcat") re_spaces = re.compile(b" +") MB = 1048576 PROGRESS_COUNT = 1024 def perl2json(filename): p2j = [ 'perl', '-MJSON', '-e', '''my %Conf;\n''' + open(filename).read() + ';\n' '''print to_json(\\%Conf, {pretty => 1});''' ] json_data = subprocess.run(p2j, stdout=subprocess.PIPE) return json.loads(json_data.stdout) class backup: def __init__(self, host, backup_nr, share="/", bpc_file_count=1): self.protocol = 0 self.cmd = [bpc_ls, "-R", "-i", "-h", host, "-n", backup_nr, "-s", share, "/"] self.f = subprocess.Popen(self.cmd, stdout=subprocess.PIPE) print(" ".join(self.cmd)) self.bpc_file_count = bpc_file_count self.read(self.f.stdout) def read(self, fd): self.total_size = 0 self.total_count = 0 self.progress = 0 minus = ord("-") slash = ord("/") colon = ord(":") while True: row = fd.readline() if not row: break if len(row) < 2 or (row[0] == slash and row[-2] == colon): continue self.total_count += 1 cols = re_spaces.split(row.strip()) # print(cols) if len(cols) > 6 and cols[1][0] == minus: try: inode, links = cols[0].split(b"/", 1) size, f_date, f_time, filename = cols[3:7] #print(int(size), filename) self.total_size += int(size)/int(links) except ValueError as err: print(err) print(row) print(self.cmd) raise # else: # print(row.decode("utf8").strip()) # progress if self.total_count > self.progress+PROGRESS_COUNT: sys.stderr.write(" %s, ~%4.2f%%\r" % ( self.total_count, self.total_count/self.bpc_file_count*100 # % )) self.progress = self.total_count if sys.argv[1:]: print( "Size: %5.3f MB" % ( backup( sys.argv[1], sys.argv[2], sys.argv[3] ).total_size/1048576 ) ) else: for host in os.listdir(PC_DIR): host_dir = os.path.join(PC_DIR, host) host_size = 0 host_count = 0 for backup_row in open(os.path.join(host_dir, "backups")): backup_nr, backup_type, d1, d2, exist_file_count, exist_size, \ new_file_count, new_size, other = \ backup_row.split("\t", 8) config = perl2json("%s/%s.pl" % (CONFIG_DIR, host)) for share in config.get("RsyncShareName", "/"): sys.stderr.write( "Running on %s/%s:%s ...\n" % (host, backup_nr, share) ) backup2 = backup( host, backup_nr, share, int(exist_file_count)+int(new_file_count) ) host_size += backup2.total_size host_count += backup2.total_count print( "%s/%s:%s: %5.3f MB / %d files" % ( host, backup_nr, share, backup2.total_size/MB, backup2.total_count ) ) print( "HOST: %s: %8.6f GB / %d files" % (host, host_size/MB/1024, host_count) ) sys.stdout.flush()