Hallo,
heute war es so weit und ich rang mich durch erstmals anstatt os pathlib zu verwenden.
Da man neben dem selber Machen am meisten durch konstruktive Kritik lernt, bitte ich um Tipps für folgenden Code:
import pathlib
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import toml
from humanize import naturalsize
SKRIPTPFAD = pathlib.Path(__file__).parent
def load_backup_config(path):
return toml.loads(path.read_text())
CONFIG = load_backup_config(pathlib.Path(SKRIPTPFAD, "config.toml"))
class Controller:
def __init__(self, backuppfad_tage, backuppfad_wochen, backuppfad_monate,
anzahl_tage, anzahl_wochen, anzahl_monate):
self.backuppfad_tage = backuppfad_tage
self.backuppfad_wochen = backuppfad_wochen
self.backuppfad_monate = backuppfad_monate
self.anzahl_tage = [anzahl_tage]
self.anzahl_wochen = [anzahl_wochen]
self.anzahl_monate = [anzahl_monate]
self.tage_anzahl_ok = False
self.wochen_anzahl_ok = False
self.monate_anzahl_ok = False
self.files_tage = None
self.files_wochen = None
self.files_monate = None
def check_number_tage(self):
self.tage_anzahl_ok, istanzahl = check_backup_number(self.backuppfad_tage, self.anzahl_tage[0])
self.anzahl_tage.append(istanzahl)
def check_number_wochen(self):
self.wochen_anzahl_ok, istanzahl = check_backup_number(self.backuppfad_wochen, self.anzahl_wochen[0])
self.anzahl_wochen.append(istanzahl)
def check_number_monate(self):
self.monate_anzahl_ok, istanzahl = check_backup_number(self.backuppfad_monate, self.anzahl_monate[0])
self.anzahl_monate.append(istanzahl)
def get_files_tage(self):
self.files_tage = get_file_name_and_size(self.backuppfad_tage)
def get_files_wochen(self):
self.files_wochen = get_file_name_and_size(self.backuppfad_wochen)
def get_files_monate(self):
self.files_monate = get_file_name_and_size(self.backuppfad_monate)
def dict_laenge_angleichen(self):
dict_laenge = max(len(self.files_tage), len(self.files_wochen), len(self.files_monate))
dicts = [self.files_tage, self.files_wochen, self.files_monate]
for dict_ in dicts:
counter = 0
while len(dict_) < dict_laenge:
dict_[f"leer_{counter}"] = ""
counter += 1
def get_file_name_and_size(pfad):
objs = {}
for obj in pfad.iterdir():
objs[obj.name] = obj.stat().st_size
return objs
def check_backup_number(backupdir, soll_anzahl):
ist_anzahl = count_files(backupdir)
if soll_anzahl == ist_anzahl:
return True, ist_anzahl
else:
return False, ist_anzahl
def count_files(pfad):
counter = -1
for counter, _ in enumerate(pfad.iterdir()):
pass
return counter + 1
def backup_anzahl_pruefen(controller):
controller.check_number_tage()
controller.check_number_wochen()
controller.check_number_monate()
def backup_files_size_abrufen(controller):
controller.get_files_tage()
controller.get_files_wochen()
controller.get_files_monate()
def get_html_farbe(anzahl):
if anzahl[0] == anzahl[1]:
return "green"
else:
return "red"
def tabelle_erstellen(controller):
tabelle = f"<tr><th colspan='2'>Tagesbackup</th><th colspan='2'>Wochenbackup</th>" \
f"<th colspan='2'>Monatsbackup</th></tr>" \
f"<tr><td colspan='2'><font color='{get_html_farbe(controller.anzahl_tage)}'>{controller.anzahl_tage[1]} von {controller.anzahl_tage[0]} vorhanden</font></td>" \
f"<td colspan='2'><font color='{get_html_farbe(controller.anzahl_wochen)}'>{controller.anzahl_wochen[1]} von {controller.anzahl_wochen[0]} vorhanden</font></td>" \
f"<td colspan='2'><font color='{get_html_farbe(controller.anzahl_monate)}'>{controller.anzahl_monate[1]} von {controller.anzahl_monate[0]} vorhanden</font></td></tr>"
for (files_tage_key, files_tage_value), \
(files_wochen_key, files_wochen_value), \
(files_monate_key, files_monate_value) in zip(controller.files_tage.items(), controller.files_wochen.items(),
controller.files_monate.items()):
if files_tage_key.startswith("leer"):
tabelle = f"{tabelle}" \
f"<tr><td></td><td></td>"
else:
tabelle = f"{tabelle}" \
f"<tr><td>{files_tage_key}</td><td>{naturalsize(files_tage_value)}</td>"
if files_wochen_key.startswith("leer"):
tabelle = f"{tabelle}" \
f"<td></td><td></td>"
else:
tabelle = f"{tabelle}" \
f"<td>{files_wochen_key}</td><td>{naturalsize(files_wochen_value)}</td>"
if files_monate_key.startswith("leer"):
tabelle = f"{tabelle}" \
f"<td></td><td></td></tr>"
else:
tabelle = f"{tabelle}" \
f"<td>{files_monate_key}</td><td>{naturalsize(files_monate_value)}</td></tr>"
return tabelle
def email_inhalt_erstellen(controller):
tabelle = tabelle_erstellen(controller)
html = f"""
<html>
<body>
<table border="2">
{tabelle}
</table>
</body>
</html>
"""
return MIMEText(html, "html")
def email_versenden(controller):
message = MIMEMultipart("alternative")
message["Subject"] = "Backupkontrolle"
message["From"] = CONFIG["mail"]["sender_email"]
message["To"] = CONFIG["mail"]["receiver_email"]
inhalt = email_inhalt_erstellen(controller)
message.attach(inhalt)
with smtplib.SMTP(CONFIG["mail"]["smtp_server"], CONFIG["mail"]["port"]) as server:
server.sendmail(CONFIG["mail"]["sender_email"], CONFIG["mail"]["receiver_email"], message.as_string())
def main():
backuppfad_tage = pathlib.Path(CONFIG["db"]["arbeitsordner"], "Tage")
backuppfad_wochen = pathlib.Path(CONFIG["db"]["arbeitsordner"], "Wochen")
backuppfad_monate = pathlib.Path(CONFIG["db"]["arbeitsordner"], "Monate")
backup_kontrolle = Controller(backuppfad_tage, backuppfad_wochen, backuppfad_monate,
CONFIG["db"]["tage"], CONFIG["db"]["wochen"],
CONFIG["db"]["monate"])
backup_anzahl_pruefen(backup_kontrolle)
backup_files_size_abrufen(backup_kontrolle)
backup_kontrolle.dict_laenge_angleichen()
email_versenden(backup_kontrolle)
if __name__ == "__main__":
main()
Display More
incron_aufrufe = 3
#Am besten eine Ramdisk erstellen oder anderweitigen tmpfs Ordner verwenden
incron_aufrufe_pfad = "/media/ramdisk/backupverwaltung/"
incron_aufrufe_datei = "aufrufe.toml"
[db]
arbeitsordner = "<arbeitsordner>"
tage = 8
tage_einzeldatei = false
wochen = 5
monate = 6
# Es wird der älteste Ordner der jeweiligen Woche kopiert
nur_ein_ordner_in_woche_kopieren = true
[mail]
smtp_server = "<serverip>"
port = 0
sender_email = "<senderemail>"
receiver_email = "<empfängermail>"
Display More
Die Vermischung von englisch und deutsch ist mir bewusst, bekomm ich aber nicht (mehr) raus. Die Formatierung von Black gefällt mir nicht. Die 2 Punkte könnt ihr also außer acht lassen.
Der Code funktioniert und erledigt was er machen soll.
2 spezielle Frage von mir:
- Wie formatier ich das in Zeile 111-113 am besten?
- Setzt man die HTML eMail iwie anders besser zusammen?
Was macht der Code überhaupt?
Da die QNAP HBS Backup App bei mir irgendwie nicht richtig mit der Versionskontrolle funktioniert, bzw. unlogisch groß das Backup wird, habe ich mir in einem anderen Skript eine eigene Versionierung geschrieben um Backups von verschiedenen Zeiträumen (Tage, Wochen, Monate) vorzuhalten.
Dieser Code hier soll mir einmal täglich eine eMail schicken, in der steht wie viele Backups im entsprechenden Tage, Wochen, Monatordner vorzufinden sind und deren Namen und Größe in einer Tabelle darzustellen.
Wie gesagt es funktioniert
EDIT:
Was mir gerade selbst noch aufgefallen ist, die Ausgabe gehört chronologisch sortiert und geprüft ob nicht nur die Anzahl, sondern auch vom Datum her die Backups vorhanden sind.
EDITEDIT:
Gerade noch einen Fehler gefunden, die Größe der Ordner bei Tagesbackup stimmt nicht behoben