Debian Linux - Millionen kleiner Dateien löschen
Beim löschen von Millionen kleiner Dateien stürzt der Server ab
Hallo Zusammen,
ich habe auf einem Debian Server ein Verzeichnis welches mehrere Millionen Session files beinhaltet.
Diese Files und das Verzeichnis werden nicht mehr benötigt und können gelöscht werden.
Meine Inode Auslastung liegt deswegen bei 95%
Nur leider führt ein Löschversuch immer zu eine Auslastung von 100% auf allen 16 CPU Kernen.
Selnst ein "ls" Befehl lässt sich nicht ausführen.
Da der Server produktiv läuft (Webserver) und über 150000 Besucher am Tag abfertigt kann ich den Server nicht vom Netz nehmen oder ein Downtime von mehreren Stunden in Kauf nehmen.
Habt Ihr noch Ideen ?
Grüß
Björn
Hallo Zusammen,
ich habe auf einem Debian Server ein Verzeichnis welches mehrere Millionen Session files beinhaltet.
Diese Files und das Verzeichnis werden nicht mehr benötigt und können gelöscht werden.
Meine Inode Auslastung liegt deswegen bei 95%
Nur leider führt ein Löschversuch immer zu eine Auslastung von 100% auf allen 16 CPU Kernen.
Selnst ein "ls" Befehl lässt sich nicht ausführen.
Da der Server produktiv läuft (Webserver) und über 150000 Besucher am Tag abfertigt kann ich den Server nicht vom Netz nehmen oder ein Downtime von mehreren Stunden in Kauf nehmen.
Habt Ihr noch Ideen ?
Grüß
Björn
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 201132
Url: https://administrator.de/forum/debian-linux-millionen-kleiner-dateien-loeschen-201132.html
Ausgedruckt am: 22.12.2024 um 16:12 Uhr
20 Kommentare
Neuester Kommentar
hallo,
vielleicht wäre es eine Idee, ein Löschskript nur für eine best. Zeit laufen zu lassen, z.B. 20 Sekunden und dass dafür dann halt zeitgesteuert, d.h. im 10/20/30 Minuten-Intervall.Da dein Server sowieso immer läuft, dürftest du in einem absehbaren Zeitraum dein Verzeichnis leer bekommen.
also in etwa so (hier gefunden)
und das ganze trägst du dann in eine crontab ein.
liebe Grüße, drnatur
vielleicht wäre es eine Idee, ein Löschskript nur für eine best. Zeit laufen zu lassen, z.B. 20 Sekunden und dass dafür dann halt zeitgesteuert, d.h. im 10/20/30 Minuten-Intervall.Da dein Server sowieso immer läuft, dürftest du in einem absehbaren Zeitraum dein Verzeichnis leer bekommen.
also in etwa so (hier gefunden)
#!/usr/sh
rm -r /verzeichnis-mit-sessionfiles &
PID=$!
sleep $(( 10 ))
kill $PID
liebe Grüße, drnatur
Hallo
xargs ist dein Freund: http://linux.101hacks.com/linux-commands/xargs-command-examples/
Etwas in der Art von "find <dir-name> -type f -mtime +30 -print0 | xargs -0 rm -f" sollte helfen. Am besten zunächst ohne den "rm -f" Teil testen
Gruß
Andi
xargs ist dein Freund: http://linux.101hacks.com/linux-commands/xargs-command-examples/
Etwas in der Art von "find <dir-name> -type f -mtime +30 -print0 | xargs -0 rm -f" sollte helfen. Am besten zunächst ohne den "rm -f" Teil testen
Gruß
Andi
Ich möchte fast wetten, beide genannten Versionen werden weiterhin nur Auslastung bringen.
Lonesome Walker
Lonesome Walker
Also: das Problem, was die beiden netten Linux-n00bs da oben leider nicht bedacht haben ist doch sehr einfach.
Ein Listing dauert EWIG, ergo wird das Lösch-Script doch besser gleich auf ein entsprechendes Muster angewandt.
Da ich bei Session-Files davon ausgehe, daß diese evtl. nach dem Muster: session_hexadezimaler String
angelegt sind, mußt Du durch einfaches Probieren von:
oder wenn das zu lange dauert:
usw. rausbekommen, wann ein Löschen möglich wird.
Tja, und dann packst Du Dir das in ein Bash-Script als Loop, bis er alle wech hat.
Das kann je nach Menge dann schon mal einen Tag dauern, hatte ich auch schon mal.
Passiert meist, wenn der Cron für das Purgen der Sessions nicht mehr aktiv ist.
Lonesome Walker
Ein Listing dauert EWIG, ergo wird das Lösch-Script doch besser gleich auf ein entsprechendes Muster angewandt.
Da ich bei Session-Files davon ausgehe, daß diese evtl. nach dem Muster: session_hexadezimaler String
angelegt sind, mußt Du durch einfaches Probieren von:
rm session_00*
rm session_000*
Tja, und dann packst Du Dir das in ein Bash-Script als Loop, bis er alle wech hat.
Das kann je nach Menge dann schon mal einen Tag dauern, hatte ich auch schon mal.
Passiert meist, wenn der Cron für das Purgen der Sessions nicht mehr aktiv ist.
Lonesome Walker
Hey Walker n00b
er wollte die Dateien löschen, das dauert bei den üblichen Dateisystemen halt. Deine Idee ist leider auch nur dann besser, wenn man schon weiß wie die Dateien benannt werden und wie viele pro Block auftreten, sonst wird dein rm nach einiger Zeit wegen zuvieler Argumente zurück kommen ohne zu löschen. Außerdem sollte er nicht unbedingt aktuelle Session löschen. Wenn er das Muster erst per ls herausfinden will wird es nichts.
Alles auch schon erlebt und erledigt
Der Linux n00b01
Andi
er wollte die Dateien löschen, das dauert bei den üblichen Dateisystemen halt. Deine Idee ist leider auch nur dann besser, wenn man schon weiß wie die Dateien benannt werden und wie viele pro Block auftreten, sonst wird dein rm nach einiger Zeit wegen zuvieler Argumente zurück kommen ohne zu löschen. Außerdem sollte er nicht unbedingt aktuelle Session löschen. Wenn er das Muster erst per ls herausfinden will wird es nichts.
Alles auch schon erlebt und erledigt
Der Linux n00b01
Andi
Richtig, jedoch nicht auf meine Art und Weise.
Bei Deinem xargs dauert das Listing länger wie das Feedback, wenn er zu viele Argumente dran hat, und dann kürzt.
Deine Idee ist leider auch nur dann
besser, wenn man schon weiß wie die Dateien benannt werden und wie viele pro Block auftreten, sonst wird dein rm nach
einiger Zeit wegen zuvieler Argumente zurück kommen ohne zu löschen.
besser, wenn man schon weiß wie die Dateien benannt werden und wie viele pro Block auftreten, sonst wird dein rm nach
einiger Zeit wegen zuvieler Argumente zurück kommen ohne zu löschen.
Richtig, jedoch dauert das max. 60 Sekunden.
Generell weiß man als Server-Admin jedoch, nach welchem Muster seine Session-Files angelegt werden, ansonsten kann man ja nachlesen...
Außerdem sollte er nicht unbedingt aktuelle
Session löschen. Wenn er das Muster erst per ls herausfinden will wird es nichts.
Session löschen. Wenn er das Muster erst per ls herausfinden will wird es nichts.
Pfff, wo gehobelt wird, fallen Späne.
Besser ein paar offene Sessions gelöscht als alle Inodes zu, dann geht gar nix mehr, okay?
Und wer sagt Dir, daß Du mit ls nachgucken mußt?
Jede Distri hat ein Schema, nach dem Session-Files angelegt werden.
Lonesome Walker
Zitat von @16568:
> Zitat von @AndiEoh:
> ----
> er wollte die Dateien löschen, das dauert bei den üblichen Dateisystemen halt.
Richtig, jedoch nicht auf meine Art und Weise.
Bei Deinem xargs dauert das Listing länger wie das Feedback, wenn er zu viele Argumente dran hat, und dann kürzt.
> Zitat von @AndiEoh:
> ----
> er wollte die Dateien löschen, das dauert bei den üblichen Dateisystemen halt.
Richtig, jedoch nicht auf meine Art und Weise.
Bei Deinem xargs dauert das Listing länger wie das Feedback, wenn er zu viele Argumente dran hat, und dann kürzt.
Das ist nur korrekt wenn er den *Test* ohne rm gegen das Verzeichnis ausführt. Es ist tatsächlich so das "find" nicht derartig blöde ist die Liste aufzubauen zu sortieren und dann weiter zu reichen wie z.B. "ls" das tun muss. D.h. es findet nicht zuerst ein listing statt und dann wird gelöscht sondern es werden soviele Argumente wie das Environment hergibt von xargs gesammelt und an rm übergeben.
> Deine Idee ist leider auch nur dann
> besser, wenn man schon weiß wie die Dateien benannt werden und wie viele pro Block auftreten, sonst wird dein rm nach
> einiger Zeit wegen zuvieler Argumente zurück kommen ohne zu löschen.
Richtig, jedoch dauert das max. 60 Sekunden.
Generell weiß man als Server-Admin jedoch, nach welchem Muster seine Session-Files angelegt werden, ansonsten kann man ja
nachlesen...
> besser, wenn man schon weiß wie die Dateien benannt werden und wie viele pro Block auftreten, sonst wird dein rm nach
> einiger Zeit wegen zuvieler Argumente zurück kommen ohne zu löschen.
Richtig, jedoch dauert das max. 60 Sekunden.
Generell weiß man als Server-Admin jedoch, nach welchem Muster seine Session-Files angelegt werden, ansonsten kann man ja
nachlesen...
Wenn man als Server-Admin weiß nach welchem Muster die Dateien wo zu welchem Zweck mit welcher Verzeichnis Hashtiefe angelegt werden weiß man auch das man die Dateianzahl begrenzen muß. Falls man das im Notfall nachlesen muß dauert es deutlich länger als 60 Sekunden. Da es wohl ein Webserver ist hängt es auch von der verwendeten Programmiersprache und der Webanwendung ab. Darin dann Blind mit rm und * Pattern drin rum zu löschen ist nicht unbedingt ein Zeichen von tiefergehendem Linux Verständnis.
> Außerdem sollte er nicht unbedingt aktuelle
> Session löschen. Wenn er das Muster erst per ls herausfinden will wird es nichts.
Pfff, wo gehobelt wird, fallen Späne.
Besser ein paar offene Sessions gelöscht als alle Inodes zu, dann geht gar nix mehr, okay?
Und wer sagt Dir, daß Du mit ls nachgucken mußt?
Jede Distri hat ein Schema, nach dem Session-Files angelegt werden.
> Session löschen. Wenn er das Muster erst per ls herausfinden will wird es nichts.
Pfff, wo gehobelt wird, fallen Späne.
Besser ein paar offene Sessions gelöscht als alle Inodes zu, dann geht gar nix mehr, okay?
Und wer sagt Dir, daß Du mit ls nachgucken mußt?
Jede Distri hat ein Schema, nach dem Session-Files angelegt werden.
Es kommt nicht auf die Distri an sondern auf die Programmiersprache (PHP, Perl, Java whatever..) und die Webanwendung. Außerdem ist diese Art der Argumentation warum deine Lösung soviel besser sein soll reichlich dünn.
BTW: Für dich nochmal extra auf einer kleinen Maschine mit 1 Mio. Files getestet
time find /var/lib/filestore/tmp -type f -mmin +1 print0 | xargs -0 rm -f
real 2m50.493s
user 0m4.072s
sys 1m51.407s
Wie die Anzahl der Disk Inodes zeigt wird auch vom ersten Moment an gelöscht, das System zeigt eine Auslastung von max. 16% für "find" und ist bis auf leicht erhöhte I/O-wait Werte Problemlos nutzbar.
Gruß
Andi
Wie bereits per PN diskutiert:
fastest way possible bei möglichst hoher Portabilität :-P
Lonesome Walker
find <dir-name> -type f -delete
fastest way possible bei möglichst hoher Portabilität :-P
Lonesome Walker
Zitat von @16568:
Wie bereits per PN diskutiert:
fastest way possible bei möglichst hoher Portabilität :-P
Wie bereits per PN diskutiert:
find <dir-name> -type f -delete
fastest way possible bei möglichst hoher Portabilität :-P
Portabilität = GNU find
Die "alten" Unices wie AIX, HP-UX etc. kennen den -delete Schalter nicht, lässt sich aber natürlich per GNU find nachrüsten und spielt hier auch keine Rolle.
Andi
Hm, okay, dann machen wir es mal anders rum:
- Hast Du den letzten Schnippsel oben getestet (den mit find und -delete, angepaßt auf Dein Verzeichnis natürlich...)?
- Was sagt cat /etc/debian_version ?
- Was sagt cat /proc/version ?
- Welches Verzeichnis willst du leeren ( Standard: /tmp )?
- Welche Scriptsprache hat die Sessions angelegt (PHP, Perl, Python, Ruby, ...)?
- Hast Du das Logverzeichnis schon mal ausgemistet oder die Logs zentral an einen Logserver schicken lassen (empfiehlt sich bei so einem Server...)?
- Hast Du den cronjob schon eingerichtet?
Lonesome Walker
Zitat von @AndiEoh:
Die "alten" Unices wie AIX, HP-UX etc. kennen den -delete Schalter nicht, lässt sich aber natürlich per GNU
find nachrüsten und spielt hier auch keine Rolle.
Die "alten" Unices wie AIX, HP-UX etc. kennen den -delete Schalter nicht, lässt sich aber natürlich per GNU
find nachrüsten und spielt hier auch keine Rolle.
ein "-exec rm {} \;" statt "-delete" sollte es auch tun.
lks
Zitat von @16568:
* Hast Du den letzten Schnippsel oben getestet (den mit find und -delete, angepaßt auf Dein Verzeichnis natürlich...)?
- Was sagt cat /etc/debian_version ?
- Was sagt cat /proc/version ?
- Welches Verzeichnis willst du leeren ( Standard: /tmp )?
- Welche Scriptsprache hat die Sessions angelegt (PHP, Perl, Python, Ruby, ...)?
- Hast Du das Logverzeichnis schon mal ausgemistet oder die Logs zentral an einen Logserver schicken lassen (empfiehlt sich bei so
- Hast Du den cronjob schon eingerichtet?
- Und welcher Prozeß greift sich denn die CPU?
lks
Noch ne frage:
Wenn nicht, würde ich einfach den befehl abschicken udn warten, bis er durch ist.
Ansonsten könntest Du eventuell mit cpuset versuchen, den load auf einige wenige Cores zu beschränken.
lks
- Wirkt sich die Auslastung von 100% auf die Antwortzeiten des Servers aus, insbesondere wenn Du den rm/ls-befehl mit nice eine niderigere priorität gibst?
Wenn nicht, würde ich einfach den befehl abschicken udn warten, bis er durch ist.
Ansonsten könntest Du eventuell mit cpuset versuchen, den load auf einige wenige Cores zu beschränken.
lks
versuch mal
oder
Wenn das damit klappt, kannst Du den Parameter von sleep sukzessive herunterschrauben. Andererseits, wenn keine neuen Dateien dazukommen und Du Zeit hast (je nach Variante 29h oder 12d bei 2^20 Dateien), sind die Dateien mit diesem Verfahren auch weg.
lks
find /data/www/www.meine-domain.tv/_tmp_/ -type f -exec rm -v {} \; -exec sleep 0.1 \;
find /data/www/www.meine-domain.tv/_tmp_/ -type f -exec rm -v {} \; -exec sleep 1.0 \;
Wenn das damit klappt, kannst Du den Parameter von sleep sukzessive herunterschrauben. Andererseits, wenn keine neuen Dateien dazukommen und Du Zeit hast (je nach Variante 29h oder 12d bei 2^20 Dateien), sind die Dateien mit diesem Verfahren auch weg.
lks
Ich hatte auch gerade das Problem,
Meine Lösung:
Dann habe ich mir folgendes Script geschrieben:
Das ganze dann mit (wenn das pwd das Verzeichnis des Scriptes ist)
starten.
Bei mir lief es dadurch ohne große Serverauslastung durch.
Keine Gewährleistung oder Garantie auf Richtgigkeit.
Meine Lösung:
mkdir /var/lib/php/session_new
chown apache:apache /var/lib/php/session_new
chmod 1777 /var/lib/php/session_new
mv /var/lib/php/session /var/lib/session_old
mv /var/lib/php/session_new /var/lib/php/session
Dann habe ich mir folgendes Script geschrieben:
#!/bin/bash
# Löschen von Millionen von PHP Session Files
array=( 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z )
array2=( 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z )
array3=( 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z )
for i in "${array[@]}"
do
for e in "${array2[@]}"
do
for f in "${array3[@]}"
do
find /var/lib/php/session_old/sess_$i$e$f* -type f | xargs -n5000 -P5 rm -f
echo sess_$i$e$f* erfolgreich gelöscht
sleep 10
done
done
done
Das ganze dann mit (wenn das pwd das Verzeichnis des Scriptes ist)
./delete.sh
starten.
Bei mir lief es dadurch ohne große Serverauslastung durch.
Keine Gewährleistung oder Garantie auf Richtgigkeit.