ตั้งแต่ที่คุณพูดถึง: ฉันไม่ จำกัด rsync:
สคริปต์เพื่อรักษามิเรอร์อนุญาตให้เพิ่มไฟล์พิเศษในการกำหนดเป้าหมาย
ด้านล่างสคริปต์ที่ทำสิ่งที่คุณอธิบาย
สคริปต์สามารถเรียกใช้ในโหมดverbose (จะตั้งค่าในสคริปต์) ซึ่งจะส่งออกความคืบหน้าของการสำรองข้อมูล (การทำมิเรอร์) ไม่จำเป็นต้องพูดว่าสามารถใช้บันทึกการสำรองข้อมูลได้:
ตัวเลือก verbose
แนวคิด
1. ในการสำรองข้อมูลครั้งแรกสคริปต์:
- สร้างไฟล์ (ในไดเรกทอรีเป้าหมาย) ซึ่งมีการระบุไฟล์และไดเรกทอรีทั้งหมด
.recentfiles
- สร้างสำเนาที่แน่นอน (มิเรอร์) ของไฟล์และไดเรกทอรีทั้งหมดในไดเรกทอรีเป้าหมาย
2. ในการสำรองข้อมูลครั้งต่อไป
- สคริปต์จะเปรียบเทียบโครงสร้างไดเรกทอรีและวันที่แก้ไขไฟล์ ไฟล์ใหม่และ dirs ในแหล่งที่มาจะถูกคัดลอกไปยังมิเรอร์ ในเวลาเดียวกันไฟล์ที่สอง (ชั่วคราว) จะถูกสร้างรายการของไฟล์ปัจจุบันและ dirs ในไดเรกทอรีแหล่ง;
.currentfiles
.
- ต่อจากนั้น
.recentfiles
(รายสถานการณ์ในการสำรองข้อมูลก่อนหน้านี้) .currentfiles
เมื่อเทียบกับ เฉพาะไฟล์.recentfiles
ที่ไม่ได้อยู่ใน.currentfiles
นั้นจะถูกลบออกอย่างชัดเจนจากแหล่งที่มาและจะถูกลบออกจากเป้าหมาย
- ไฟล์ที่คุณเพิ่มด้วยตนเองไปยังโฟลเดอร์เป้าหมายไม่ได้อยู่ในสคริปต์ "เห็น" แล้วและถูกทิ้งไว้ตามลำพัง
- ในที่สุดการ
.currentfiles
เปลี่ยนชั่วคราวจะ.recentfiles
ให้บริการรอบการสำรองต่อไปและอื่น ๆ
สคริปต์
#!/usr/bin/env python3
import os
import sys
import shutil
dr1 = sys.argv[1]; dr2 = sys.argv[2]
# --- choose verbose (or not)
verbose = True
# ---
recentfiles = os.path.join(dr2, ".recentfiles")
currentfiles = os.path.join(dr2, ".currentfiles")
if verbose:
print("Counting items in source...")
file_count = sum([len(files)+len(d) for r, d, files in os.walk(dr1)])
print(file_count, "items in source")
print("Reading directory & file structure...")
done = 0; chunk = int(file_count/5); full = chunk*5
def show_percentage(done):
if done % chunk == 0:
print(str(int(done/full*100))+"%...", end = " ")
for root, dirs, files in os.walk(dr1):
for dr in dirs:
if verbose:
if done == 0:
print("Updating mirror...")
done = done + 1
show_percentage(done)
target = os.path.join(root, dr).replace(dr1, dr2)
source = os.path.join(root, dr)
open(currentfiles, "a+").write(target+"\n")
if not os.path.exists(target):
shutil.copytree(source, target)
for f in files:
if verbose:
done = done + 1
show_percentage(done)
target = os.path.join(root, f).replace(dr1, dr2)
source = os.path.join(root, f)
open(currentfiles, "a+").write(target+"\n")
sourcedit = os.path.getmtime(source)
try:
if os.path.getmtime(source) > os.path.getmtime(target):
shutil.copy(source, target)
except FileNotFoundError:
shutil.copy(source, target)
if verbose:
print("\nChecking for deleted files in source...")
if os.path.exists(recentfiles):
recent = [f.strip() for f in open(recentfiles).readlines()]
current = [f.strip() for f in open(currentfiles).readlines()]
remove = set([f for f in recent if not f in current])
for f in remove:
try:
os.remove(f)
except IsADirectoryError:
shutil.rmtree(f)
except FileNotFoundError:
pass
if verbose:
print("Removed:", f.split("/")[-1])
if verbose:
print("Done.")
shutil.move(currentfiles, recentfiles)
วิธีใช้
- คัดลอกสคริปต์ลงในไฟล์เปล่าบันทึกเป็น
backup_special.py
เปลี่ยนถ้าคุณต้องการ - ตัวเลือก verbose ในส่วนหัวของสคริปต์:
# --- choose verbose (or not)
verbose = True
# ---
รันด้วยซอร์สและเป้าหมายเป็นอาร์กิวเมนต์:
python3 /path/to/backup_special.py <source_directory> <target_directory>
ความเร็ว
ฉันทดสอบสคริปต์ในไดเรกทอรี 10 GB โดยมีไฟล์และไดร์เวอร์ถึง 40,000 ไฟล์ในไดรฟ์เครือข่าย (NAS) ของฉันมันทำให้การสำรองข้อมูลในเวลาเดียวกับ rsync
การอัปเดตไดเรกทอรีทั้งหมดใช้เวลามากกว่า rsync เพียงไม่กี่วินาทีในไฟล์ 40.000 ซึ่งเป็นที่ยอมรับ imo และไม่แปลกใจเนื่องจากสคริปต์ต้องเปรียบเทียบเนื้อหากับการสำรองข้อมูลที่ทำล่าสุด