Tôi sẽ sử dụng Python cho nhiệm vụ đó. Nó có thể dẫn đến nhiều mã hơn một giải pháp bash thuần túy, nhưng:
- nó (IMO) dễ kiểm tra hơn, chỉ cần sử dụng
người khó tính
hoặc thống nhất
mô-đun
- nó có thể đọc được đối với những người không sử dụng Linux (ngoại trừ
get_device
chức năng dành riêng cho Linux ...)
- bắt đầu dễ dàng hơn (một lần nữa IMO)
- Nếu bạn muốn gửi một số email thì sao? Để kích hoạt hành động mới? Các tập lệnh có thể được làm giàu dễ dàng bằng ngôn ngữ lập trình như Python.
Kể từ Python 3.3, đóng cửa
mô-đun đi kèm với một chức năng có tên disk_usage
. Nó có thể được sử dụng để lấy mức sử dụng đĩa dựa trên một thư mục nhất định.
Vấn đề nhỏ là tôi không biết cách dễ dàng lấy tên của đĩa, I.E, /dev/sdb
, mặc dù có thể sử dụng đĩa của nó (sử dụng bất kỳ thư mục nào được gắn trên /dev/sdb
, trong trường hợp của tôi $HOME
Ví dụ). Tôi đã viết một chức năng gọi là get_device
vì mục đích này.
#!/usr/bin/env python3
nhập argparse
từ os.path nhập getmtime
từ Shutil nhập disk_usage, rmtree
từ thoát nhập sys
từ đường dẫn nhập pathlib
từ gõ nhập Iterator, Tuple
def get_device(path: Path) -> str:
"""Tìm phần gắn kết cho một thư mục nhất định. Điều này chỉ cần thiết cho mục đích ghi nhật ký."""
# Đọc /etc/mtab để tìm hiểu về các điểm gắn kết
mtab_entries = Đường dẫn("/etc/mtab").read_text().splitlines()
# Tạo một lệnh của các điểm và thiết bị gắn kết
mount_points = dict([list(reversed(line.split(" ")[:2])) cho dòng trong mtab_entries])
# Tìm điểm gắn kết của đường dẫn đã cho
trong khi path.resolve(True).as_posix() không có trong mount_points:
đường dẫn = đường dẫn.parent
# Trả lại thiết bị được liên kết với điểm gắn kết
trả về mount_points[path.as_posix()]
def get_directory_and_device(path: str) -> Tuple[str, Path]:
"""Thoát quá trình nếu thư mục không tồn tại."""
fs_path = Đường dẫn(đường dẫn)
# Đường dẫn phải tồn tại
nếu không fs_path.exists():
print(f"ERROR: Không có thư mục nào như vậy: {path}")
thoát(1)
# Và đường dẫn phải là một thư mục hợp lệ
nếu không fs_path.is_dir():
print(f"Đường dẫn phải là một thư mục chứ không phải tệp: {path}")
thoát(1)
# Lấy thiết bị
thiết bị = get_device(fs_path)
trả lại thiết bị, fs_path
def get_disk_usage(path: Path) -> float:
# Shutil.disk_usage hỗ trợ Đường dẫn giống như các đối tượng nên không cần chuyển thành chuỗi
cách sử dụng = disk_usage(đường dẫn)
# Nhận mức sử dụng đĩa theo tỷ lệ phần trăm
trả lại mức sử dụng.đã sử dụng/sử dụng.tổng * 100
def remove_file_or_directory(path: Path) -> Không có:
"""Xóa đường dẫn đã cho, có thể là thư mục hoặc tệp."""
# Xóa các tệp
nếu đường dẫn.is_file():
đường dẫn.unlink()
# Xóa đệ quy cây thư mục
nếu đường dẫn.is_dir():
rmtree(đường dẫn)
def find_oldest_files(
đường dẫn: Đường dẫn, mẫu: str = "*", ngưỡng: int = 80
) -> Trình lặp [Đường dẫn]:
"""Lặp lại trên các tệp hoặc thư mục có trong một thư mục khớp với mẫu đã cho."""
# Liệt kê các tệp trong thư mục được nhận làm đối số và sắp xếp chúng theo độ tuổi
tệp = đã sắp xếp (path.glob (mẫu), key = getmtime)
# Đường dẫn tệp lợi nhuận cho đến khi mức sử dụng thấp hơn ngưỡng
cho tệp trong tệp:
cách sử dụng = get_disk_usage(đường dẫn)
nếu mức sử dụng < ngưỡng:
nghỉ
tập tin năng suất
chắc chắn check_and_clean(
đường dẫn: str,
ngưỡng: int = 80,
xóa: bool = Sai,
) -> Không có:
"""Chức năng chính"""
thiết bị, fspath = get_directory_and_device(path)
# Shutil.disk_usage hỗ trợ Đường dẫn giống như các đối tượng nên không cần chuyển thành chuỗi
cách sử dụng = disk_usage(đường dẫn)
# Hành động nếu cần
nếu mức sử dụng > ngưỡng:
in(
f"Mức sử dụng đĩa lớn hơn ngưỡng: {usage:.2f}% > {threshold}% ({device})"
)
# Lặp lại các tệp để xóa
đối với tệp trong find_oldest_files(fspath, "*", ngưỡng):
print(f"Xóa tệp {file}")
nếu loại bỏ:
remove_file_or_directory(file)
def main() -> Không có:
trình phân tích cú pháp = argparse.ArgumentParser(
description="Dọn sạch các tập tin cũ khi mức sử dụng đĩa vượt quá giới hạn."
)
trình phân tích cú pháp.add_argument(
"path", help="Đường dẫn thư mục mà các tập tin sẽ bị xóa", gõ=str
)
trình phân tích cú pháp.add_argument(
"--ngưỡng",
"-t",
metavar="T",
help="Ngưỡng sử dụng theo tỷ lệ phần trăm",
loại = int,
mặc định = 80,
)
trình phân tích cú pháp.add_argument(
"--gỡ bỏ",
"--rm",
help="Các tập tin không bị xóa trừ khi tùy chọn --removed hoặc --rm được chỉ định",
hành động="store_true",
mặc định=Sai,
)
args = trình phân tích cú pháp.parse_args()
check_and_clean(
args.path,
ngưỡng=args.threshold,
loại bỏ = args. loại bỏ,
)
nếu __name__ == "__main__":
chủ yếu()
Nếu bạn cần sắp xếp nhiều tác vụ bằng CRON, bạn nên tập hợp một số mã Python làm thư viện và sử dụng lại mã này trong nhiều tác vụ.
CHỈNH SỬA: Cuối cùng tôi đã thêm phần CLI vào tập lệnh, tôi nghĩ tôi sẽ tự mình sử dụng nó