Skip to content

Instantly share code, notes, and snippets.

@Raniz85
Created November 13, 2015 08:32
Show Gist options
  • Save Raniz85/25525b5724dd3c03edca to your computer and use it in GitHub Desktop.
Save Raniz85/25525b5724dd3c03edca to your computer and use it in GitHub Desktop.
#!/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