Aș folosi Python pentru o astfel de sarcină. Ar putea duce la mai mult cod decât o soluție bash pură, dar:
- este (IMO) mai ușor de testat, doar utilizați
pytest
sau unitest
modul
- este lizibil pentru persoanele care nu sunt Linux (cu excepția
get_device
funcție care este specifică Linux...)
- este mai ușor să începeți (din nou IMO)
- Ce se întâmplă dacă vrei să trimiți niște e-mailuri? Pentru a declanșa noi acțiuni? Scripturile pot fi îmbogățite cu ușurință cu un limbaj de programare precum Python.
De la Python 3.3, shutil
modulul vine cu o funcție numită utilizare_disc
. Poate fi folosit pentru a obține utilizarea discului pe baza unui director dat.
Problema minoră este că nu știu cum să obțin cu ușurință numele discului, I.E, /dev/sdb
, chiar dacă este posibil să obțineți utilizarea discului (folosind orice director montat pe /dev/sdb
, În cazul meu $HOME
de exemplu). Am scris o funcție numită get_device
în acest scop.
#!/usr/bin/env python3
import argparse
din os.path import getmtime
din shutil import disk_usage, rmtree
de la ieșire de import sys
din calea de import pathlib
de la tastarea import Iterator, Tuple
def get_device(cale: Cale) -> str:
"""Găsiți montarea pentru un director dat. Acest lucru este necesar doar pentru logare."""
# Citiți /etc/mtab pentru a afla despre punctele de montare
mtab_entries = Path("/etc/mtab").read_text().splitlines()
# Creați un dict de puncte de montare și dispozitive
mount_points = dict([listă(inversat(line.split(" ")[:2])) pentru linia din mtab_entries])
# Găsiți punctul de montare al căii date
în timp ce path.resolve(True).as_posix() nu este în mount_points:
cale = cale.părinte
# Dispozitivul de returnare asociat cu punctul de montare
returnează punctele_montare[path.as_posix()]
def get_directory_and_device(cale: str) -> Tuple[str, Path]:
"""Ieșiți din proces dacă directorul nu există."""
fs_path = Cale(cale)
# Calea trebuie să existe
dacă nu fs_path.exists():
print(f"EROARE: Nu există un astfel de director: {cale}")
ieșire (1)
# Și calea trebuie să fie un director valid
dacă nu fs_path.is_dir():
print(f"Calea trebuie să fie un director și nu un fișier: {cale}")
ieșire (1)
# Obțineți dispozitivul
dispozitiv = get_device(fs_path)
dispozitiv de returnare, fs_path
def get_disk_usage(cale: cale) -> float:
# Shuil.disk_usage suport Obiecte asemănătoare căii, deci nu este nevoie să aruncați în șir
utilizare = disk_usage(cale)
# Obțineți utilizarea discului în procente
return usage.used / usage.total * 100
def remove_file_or_directory(cale: Cale) -> Niciunul:
"""Eliminați calea dată, care poate fi un director sau un fișier."""
# Eliminați fișierele
dacă calea.is_file():
path.unlink()
# Ștergeți recursiv arbori de directoare
dacă calea.is_dir():
rmtree(cale)
def găsiți cele mai vechi_fișiere(
cale: cale, model: str = "*", prag: int = 80
) -> Iterator[Cale]:
"""Repetați fișierele sau directoarele prezente într-un director care se potrivesc cu modelul dat."""
# Listați fișierele din directorul primit ca argument și sortați-le după vârstă
fișiere = sortate(cale.glob(model), cheie=getmtime)
# Randamentul căilor fișierelor până când utilizarea este mai mică decât pragul
pentru fișier în fișiere:
utilizare = get_disk_usage(cale)
dacă utilizare < prag:
pauză
dosar de randament
def check_and_clean(
cale: str,
prag: int = 80,
eliminați: bool = False,
) -> Niciuna:
"""Functie principala"""
dispozitiv, fspath = get_directory_and_device(cale)
# Shuil.disk_usage suport Obiecte asemănătoare căii, deci nu este nevoie să aruncați în șir
utilizare = disk_usage(cale)
# Luați măsuri dacă este necesar
dacă utilizare > prag:
imprimare(
f„Utilizarea discului este mai mare decât pragul: {usage:.2f}% > {threshold}% ({dispozitiv})”
)
# Iterați peste fișiere pentru a le elimina
pentru fișierul din find_oldest_files(fspath, "*", threshold):
print(f"Se elimină fișierul {fișier}")
dacă eliminați:
remove_file_or_directory(fișier)
def main() -> Nici unul:
parser = argparse.ArgumentParser(
description="Șterge fișierele vechi când utilizarea discului este peste limita."
)
parser.add_argument(
"path", help="Cale directorului unde fișierele ar trebui să fie curățate", tip=str
)
parser.add_argument(
"--prag",
"-t",
metavar="T",
help="Pragul de utilizare în procent",
tip=int,
implicit=80,
)
parser.add_argument(
"--elimina",
"--rm",
help="Fișierele nu sunt eliminate decât dacă este specificată opțiunea --removed sau --rm",
action="store_true",
implicit=fals,
)
args = parser.parse_args()
verifica_si_curata(
args.path,
prag=args.threshold,
remove=args.remove,
)
if __name__ == "__main__":
principal()
Dacă aveți nevoie să orchestrați multe sarcini folosind CRON, ar putea merita să puneți împreună un cod Python ca bibliotecă și să reutilizați acest cod în multe sarcini.
EDIT: Am adăugat în sfârșit partea CLI în script, cred că o voi folosi și eu