Created
November 13, 2015 08:32
-
-
Save Raniz85/25525b5724dd3c03edca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Simple script for mirroring a directory to all plugged in USB drives using Rsync in parallell | |
import math | |
import os | |
import subprocess | |
import time | |
class Drive: | |
def __init__(self, disk): | |
self.driveName = disk[4:-10] | |
self.diskPath = os.path.join('/dev', 'disk', 'by-id', disk) | |
self.mountPath = os.path.join('/media', 'usb-mirror', self.driveName) | |
self.capacity = int(subprocess.check_output(["sudo", "blockdev", "--getsize64", self.diskPath])) | |
self.mounted = False | |
def mount(self): | |
if not os.path.exists(self.mountPath): | |
os.makedirs(self.mountPath) | |
print('Mounting {} on {}'.format(self.driveName, self.mountPath)) | |
try: | |
subprocess.check_call(["sudo", "mount", self.diskPath, self.mountPath]) | |
self.mounted = True | |
except subprocess.CalledProcessError: | |
pass | |
def unmount(self): | |
print('Unmounting {}'.format(self.driveName)) | |
return subprocess.Popen(["sudo", "umount", self.diskPath]) | |
def mirror(self): | |
if self.mounted: | |
return subprocess.Popen(["rsync", "-v", "--recursive", "--delete-before", "--update", "./", self.mountPath], stdout=subprocess.PIPE) | |
else: | |
return None | |
drives = [] | |
for root, dirs, files in os.walk('/dev/disk/by-id'): | |
for name in files: | |
if name.startswith("usb-") and name.endswith("part1"): | |
drives.append(Drive(name)) | |
print("Will sync {} to the following drives".format(os.getcwd())) | |
for drive in drives: | |
print(" {:<45} {:>6} GB".format(drive.driveName, round(drive.capacity / 1024**3, 2))) | |
input("Press enter to continue or ^C to exit") | |
start = time.time() | |
times = dict() | |
processes = dict() | |
for drive in drives: | |
print("Mirroring to drive {}".format(drive.driveName)) | |
drive.mount() | |
process = drive.mirror() | |
if process is not None: | |
processes[drive] = (process, False) | |
else: | |
print("Warning: could not start mirroring of drive {}".format(drive.driveName)) | |
print() | |
unmounts = dict() | |
outputs = dict() | |
while len(processes) > 0: | |
for drive, (process, umount) in list(processes.items()): | |
if process.poll() is not None: | |
if umount: | |
times[drive] = time.time() | |
del processes[drive] | |
else: | |
processes[drive] = (drive.unmount(), True) | |
output = process.communicate()[0].decode("utf-8") | |
outputs[drive] = output.strip().splitlines() | |
time.sleep(0.05) | |
end = time.time() | |
print() | |
print("{:^45} {:^12} {:^12}".format("Drive", "Time", "Speed")) | |
for drive, end_time in sorted(times.items(), key=lambda x: x[1]): | |
size = int(outputs[drive][-2].split()[1].replace(",", "")) | |
duration = end_time - start | |
print("{:<45} {:>10} s {:>10} MB/s".format(drive.driveName, round(duration, 2), round(size / 1024**2 / duration, 2))) | |
print() | |
print("Total time: {} s".format(round(end - start, 2))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment