Vì bạn đã đề cập: Tôi không giới hạn ở rsync:
Script để duy trì máy nhân bản, cho phép thêm tệp bổ sung vào mục tiêu
Bên dưới một kịch bản thực hiện chính xác những gì bạn mô tả.
Kịch bản có thể được chạy trong chế độ dài dòng (sẽ được đặt trong tập lệnh), sẽ tạo ra tiến trình sao lưu (phản chiếu). Không cần phải nói điều này cũng có thể được sử dụng để đăng nhập các bản sao lưu:
Tùy chọn dài dòng
Khái niệm
1. Trong lần sao lưu đầu tiên, tập lệnh:
- tạo một tệp (trong thư mục đích), trong đó tất cả các tệp và thư mục được liệt kê;
.recentfiles
- tạo một bản sao chính xác (bản sao) của tất cả các tệp và thư mục trong thư mục đích
2. Tiếp theo và sao lưu
- Kịch bản so sánh cấu trúc thư mục và (các) ngày sửa đổi của các tệp. Các tập tin và thư mục mới trong nguồn được sao chép vào máy nhân bản. Đồng thời một tệp thứ hai (tạm thời) được tạo, liệt kê các tệp và thư mục hiện tại trong thư mục nguồn;
.currentfiles
.
- Sau đó,
.recentfiles
(liệt kê tình huống trên bản sao lưu trước) được so sánh với .currentfiles
. Chỉ các tệp .recentfiles
không có trong .currentfiles
đó rõ ràng bị xóa khỏi nguồn và sẽ bị xóa khỏi mục tiêu.
- Các tập tin bạn đã thêm thủ công vào thư mục đích không nằm trong tập lệnh "được nhìn thấy" và được để lại một mình.
- Cuối cùng, tạm thời
.currentfiles
được đổi tên thành .recentfiles
để phục vụ chu kỳ sao lưu tiếp theo, v.v.
Kịch bản
#!/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)
Cách sử dụng
- Sao chép tập lệnh vào một tập tin trống, lưu nó dưới dạng
backup_special.py
Thay đổi - nếu bạn muốn- tùy chọn dài dòng trong phần đầu của tập lệnh:
# --- choose verbose (or not)
verbose = True
# ---
Chạy nó với nguồn và đích làm đối số:
python3 /path/to/backup_special.py <source_directory> <target_directory>
Tốc độ
Tôi đã thử nghiệm tập lệnh trên thư mục 10 GB với khoảng 40.000 tệp và thư mục trên ổ đĩa mạng (NAS), nó đã tạo bản sao lưu trong cùng thời gian với rsync.
Cập nhật toàn bộ thư mục chỉ mất một vài giây hơn rsync, trên 40.000 tác phẩm, đó là imo chấp nhận được và không ngạc nhiên, vì kịch bản cần so sánh nội dung để sao lưu cuối cùng thực hiện.