Script zum automatischen Löschen der ältesten Dateien, falls Ordner größer als...

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo, ich bin auf der Suche nach einem Skript für meinen Raspberry Pi.
    Das Skript soll die ältesten X Prozent der Dateien in einem Ordner löschen, falls die Dateien im Ordner größer als Y GB sind. Gedacht ist das ganze für eine Überwachungskamera, die die Dateien so lange wie möglich behalten soll (sonst könnte ich ja einfach "Lösche Dateien, die älter als Z Tage sind" machen).

    Ich habe mal angefangen mit:

    [code=php]Speicher_max=16

    if [du -sh /verzeichnis -ge Speicher_max]
    then[/php]

    Wie könnte es weiter gehen, oder hab ich da schon den ersten Fehler? Leider kenne ich mich mit Linux noch nicht aus bzw. versuche mich gerade etwas einzuarbeiten. Danke =):danke_ATDE:

  • Script zum automatischen Löschen der ältesten Dateien, falls Ordner größer als...? Schau mal ob du hier fündig wirst!

  • find ist sehr mächtig, deshalb wären Anfänger damit vermutlich schnell überfordert und sie lernen dabei nix (weil sies nur vorgekaut umgesetzt kriegen)

    Deshalb würde ich das eher mit etwas einfacherem umsetzen, würde dann zwar auch umfangreicher werden - but who cares, hauptsache derjenige der etwas haben will versteht was das tut und lernt dabei auch noch für später was :D


    Also, fangen wir erst mal damit an festzulegen was das Script können soll:

    - Es soll X Prozent löschen?´:huh: (das wäre afaik auch mit find nicht machbar)
    Dazu müsste man also erst mal die Ordnergröße ermitteln und dann quasi ausrechnen wieviel Dateien gelöscht werden müssen um X Prozent frei zu kriegen... Ich denke einfacher wäre es nur festzulegen wieviel Speicherplatz bereinigt werden muss, also zum Beispiel 10MB frei machen. Das Script dann einfach über crontab öfters ausführen lassen und man hat damit keine weiteren Probleme.

    -- Falls Dateien im Ordner größer als Y GB sind :huh:
    Meinst du damit wirklich einzelne Dateien oder die allg. Ordnergröße?

  • Kleiner Schreibfehler @ Tell, anstatt size sollte das $size sein :)

    Code
    size=$(du -s /verzeichnis | grep -o '[0-9]*')
    
    
    if [ $size -gt 123456789 ]
    then
      loeschen
    fi

    Und wärs hier nicht auch besser du -sk zu nutzen :huh:

    Er will aber auch nicht einfach alles löschen sondern nur eine bestimmte Anzahl, also X-Prozente

  • Also ich hab mal was gebastelt, was den Anforderungen des TE's ungefähr entspricht:

    Spoiler anzeigen

    Zur Demonstration hab ich die Firmware des RaspberryPI's nach /tmp/test/ kopiert und den Pfad für die DIR Variable im Script entsprechend angepasst.

    Das Verzeichnis /tmp/test/ ist 59 MB (59864 KB) groß. Space_Max hab ich auf 50 und Space_Min auf 48 eingestellt - diese Angaben sind wie gesagt in MB, das Script rechnet es dann aber auf KB um da die Ausgabe vom du -sk Befehl auch auf KB fixiert ist.

    Führe ich das Script aus, wird eine Datei gelöscht und anschließend die Verzeichnisgröße von /tmp/test/ erneut geprüft. Sobald die Verzeichnisgröße kleiner als Space_Min ist hört das Script auf.

    Das Script beachtet aber nicht das Alter einer Datei! Sowas müsste man noch einbauen!

    Ich hab auch Ausgaben eingebaut, die anzeigen was gemacht wird usw und das sähe dann wie folgt aus:

    Spoiler anzeigen


    Wenn Fragen zur Funktionsweise o.ä. ist erklär ich das gerne (später, muss jetzt ins Bett) ;)

  • Vielen Dank für die ganzen schnellen Antworten!

    Zitat

    - Es soll X Prozent löschen?´Icon_question2 (das wäre afaik auch mit find nicht machbar)
    Dazu müsste man also erst mal die Ordnergröße ermitteln und dann quasi ausrechnen wieviel Dateien gelöscht werden müssen um X Prozent frei zu kriegen... Ich denke einfacher wäre es nur festzulegen wieviel Speicherplatz bereinigt werden muss, also zum Beispiel 10MB frei machen. Das Script dann einfach über crontab öfters ausführen lassen und man hat damit keine weiteren Probleme.

    Das wäre auch möglich und würde auch vollkommen die Funktion erfüllen :)

    Zitat

    -- Falls Dateien im Ordner größer als Y GB sind Icon_question2
    Meinst du damit wirklich einzelne Dateien oder die allg. Ordnergröße?

    Damit meine ich natürlich die gesamte Ordnergröße :)

    Das Skript von dir, meigrafd, ist schon mal super. Wie könnte ich denn nun noch das Dateialter berücksichtigen? Irgendwie müsste das Skript alle Dateien nach ihrem Änderungsdatum sortieren und immer die jeweils älteste Datei löschen.

    Das Skript habe ich mit den Erläuterungen verstanden (wäre aber selbst nicht darauf gekommen :)).

    :danke_ATDE::danke_ATDE:

    PS: Beim googlen bin ich jetzt auf einen code gestoßen, der wohl die älteste Datei findet. Wie könnte ich den noch integrieren?

    Code
    (export LC_ALL=C
     find . -type f -printf '%T@\t%p\0' 2>/dev/null |
       sort -zg | tr '\0\n' '\n\0' | head -n 1 |
       cut -f2- | tr '\0' '\n')

    Müsste ich da jetzt einfach das "f" vorher definieren?

    Also so in der Art:

    Einmal editiert, zuletzt von thehand (11. November 2014 um 14:19)

  • Naja dafür gäbe es (wie immer) mehrere Möglichkeiten.

    1. die von dreamshader schon erwähnte Möglichkeit mithilfe des Befehls find die "last modified time" ermitteln.
    Darüber ließe sich eigentlich auch direkt das löschen ausführen lassen (google Suche nach: /bin/bash find old files), allerdings löscht das einfach alle die dem Suchmuster entspricht ohne Rücksicht auf Prozente bzw "mach nur 10MB frei", und es gibt auch nichts sonderlich aus - also es ginge auch ein Einzeiler (eine Zeile Code), aber das is nicht so schick :D

    2. Mithilfe des Befehls stat die "last modified time" ermitteln.


    Für die 1. Möglichkeit verändern wir zunächst nur die Zeile for f in $(ls $DIR/*); do , denn damit werden ja die Dateien aufgelistet. Und zwar ändern wir das Beispielsweise in:

    Code
    for f in $(find $DIR -type f -mtime +3); do


    Damit würden nur Dateien auflisten werden die eine "last modified time" älter als 3 Tage haben.

    Um anschließend noch die Ausgabe zu verschönern ändern wir die Zeilen bezüglich echo "Deleting $f to get ${fSize}KB space free." o.ä. noch so dass nur die Datei angezeigt wird, nicht der vollständige Pfad. Das erreicht man mithilfe des Befehls basename welcher den Pfad rausschneiden und nur den Dateinamen ausgibt:

    Code
    echo "Deleting $(basename $f) to get ${fSize}KB space free."


    Ein einfacher Test zur Veranschaulichung sähe in der Konsole einfach so aus: basename /root/.rpi-firmware/start_cd.elf was dann nur start_cd.elf ausgibt ;)

    Das vollständige Script könnte dann wie folgt aussehen:

    Spoiler anzeigen


    Für die 2.Möglichkeit müsste das Script etwas mehr erweitert werden, da wir selber den EPOCH Unterschied der Datei und aktuell errechnen müssten.

    Also zunächst ermitteln wir die aktuelle Epoch (auch Unix Timestamp genannt, das sind die Sekunden die seit dem 1.1.1970 vergangen sind, standardisiert). Das kriegen wir mit dem Befehl date +%s
    Dann ermitteln wir mithilfe von stat diese Epoch ebenfalls von der jeweiligen Datei: stat -c%Y $f also zum Beispiel stat -c%Y /root/.bashrc
    Und jetzt brauchen wir noch den Zeitraum zum löschen, wenn also die Datei älter als diese Differenz ist wird sie gelöscht. Nehmen wir wieder das Beispiel 3 Tage: 60 Sekunden * 60 Minuten * 24 Stunden ... entspricht ein Tag, also hat ein Tag 86400 Sekunden. Mal 3 wären: 259200
    Nun rechnen wir die besagte Differenz aus, von der aktuellen Epoch und der Datei-Epoch indem wir letzteres von ersteres abziehen: $nowEpoch - $fileEpoch
    Ist diese Differenz nun größer als 259200 Sekunden wissen wir das die Datei älter als 3 Tage ist und soll gelöscht werden :fies:

    Das fertige Script für diese Möglichkeit sähe wie folgt aus:

    Spoiler anzeigen


    //EDIT: Noch eine Möglichkeit => FTP-Server, Ordner automatisch aufräumen

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!