bblanke
Goto Top

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

Content-Key: 201132

Url: https://administrator.de/contentid/201132

Printed on: April 25, 2024 at 22:04 o'clock

Member: drnatur
drnatur Feb 01, 2013 at 13:07:13 (UTC)
Goto Top
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)
#!/usr/sh
rm -r /verzeichnis-mit-sessionfiles &
PID=$!
sleep $(( 10 ))
kill $PID
und das ganze trägst du dann in eine crontab ein.

liebe Grüße, drnatur
Member: AndiEoh
AndiEoh Feb 01, 2013 at 13:16:22 (UTC)
Goto Top
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 face-wink

Gruß

Andi
Mitglied: 16568
16568 Feb 02, 2013 at 11:43:51 (UTC)
Goto Top
Ich möchte fast wetten, beide genannten Versionen werden weiterhin nur Auslastung bringen.


Lonesome Walker
Member: bblanke
bblanke Feb 02, 2013 updated at 14:43:45 (UTC)
Goto Top
Die Wette hast Du gewonnen !
Hast Du noch eine Idee ?
Mitglied: 16568
16568 Feb 02, 2013 at 22:27:47 (UTC)
Goto Top
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:

rm session_00*
oder wenn das zu lange dauert:
rm session_000*
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
Member: AndiEoh
AndiEoh Feb 03, 2013 at 12:43:18 (UTC)
Goto Top
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
Mitglied: 16568
16568 Feb 03, 2013 at 16:37:15 (UTC)
Goto Top
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.

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...

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.


Lonesome Walker
Member: AndiEoh
AndiEoh Feb 04, 2013 at 09:31:25 (UTC)
Goto Top
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.


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...


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.

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
Mitglied: 16568
16568 Feb 05, 2013 updated at 13:04:16 (UTC)
Goto Top
Wie bereits per PN diskutiert:

find <dir-name> -type f -delete

fastest way possible bei möglichst hoher Portabilität :-P


Lonesome Walker
Member: AndiEoh
AndiEoh Feb 06, 2013 at 13:37:43 (UTC)
Goto Top
Zitat von @16568:
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
Member: bblanke
bblanke Feb 08, 2013 at 11:32:03 (UTC)
Goto Top
Hallo Zusammen,

erstmal Danke für Eure Antworten und Tipps.

Leider hat es nicht zum gewünschten Erfolg geführt !

Gruß
Björn
Mitglied: 16568
16568 Feb 08, 2013 at 14:14:31 (UTC)
Goto Top
Zitat von @bblanke:
Leider hat es nicht zum gewünschten Erfolg geführt !

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
Member: AndiEoh
AndiEoh Feb 08, 2013 at 14:35:46 (UTC)
Goto Top
Vor allem: In welcher Form hat es nicht funktioniert bzw. was war den die Fehlermeldung??
Member: Lochkartenstanzer
Lochkartenstanzer Feb 08, 2013 at 14:43:38 (UTC)
Goto Top
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.

ein "-exec rm {} \;" statt "-delete" sollte es auch tun.

lks
Member: Lochkartenstanzer
Lochkartenstanzer Feb 08, 2013 at 14:45:37 (UTC)
Goto Top
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
einem Server...)?
  • Hast Du den cronjob schon eingerichtet?

  • Und welcher Prozeß greift sich denn die CPU?

lks
Member: bblanke
bblanke Feb 12, 2013 at 12:43:18 (UTC)
Goto Top
Hallo Zusammen:

Was sagt cat /etc/debian_version ?
6.0.5

Was sagt cat /proc/version ?
Linux version 2.6.32-5-amd64 (Debian 2.6.32-45) (dannf@debian.org) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 SMP Sun May 6 04:00:17 UTC 2012

Welches Verzeichnis willst du leeren ( Standard: /tmp )?

/data/www/www.meine-domain.tv/_tmp_/

Welche Scriptsprache hat die Sessions angelegt (PHP, Perl, Python, Ruby, ...)?
PHP

Hast Du den cronjob schon eingerichtet?
Nein

Und welcher Prozeß greift sich denn die CPU?

Je nach dem was ich ausführe - mal ls mal rm etc...

Gruß Björn
Member: Lochkartenstanzer
Lochkartenstanzer Feb 16, 2013 at 10:53:18 (UTC)
Goto Top
Noch ne frage:

  • 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
Member: bblanke
bblanke Feb 16, 2013 at 12:50:02 (UTC)
Goto Top
Hey LKS,

also ein absetzen des rm mit nice führt zum selben Ergebnis.
Nach ca. 3 Sekunden sind alle Seiten auf dem Server nicht mehr erreichbar.

Gruß
Björn
Member: Lochkartenstanzer
Lochkartenstanzer Feb 17, 2013 updated at 09:58:08 (UTC)
Goto Top
versuch mal

find  /data/www/www.meine-domain.tv/_tmp_/ -type f -exec rm -v {} \; -exec  sleep 0.1 \;
oder
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. face-smile

lks
Member: Ernestos
Ernestos Feb 23, 2014 updated at 12:55:08 (UTC)
Goto Top
Ich hatte auch gerade das Problem,
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.