So bereinigen Sie den temporären Ordner unter Linux sicher

So bereinigen Sie den temporären Ordner unter Linux sicher

Ich verwende RAM für mein tmpfs /tmp, 2 GB, um genau zu sein. Normalerweise reicht das aus, aber manchmal erstellen Prozesse dort Dateien und können diese nicht aufräumen. Das kann passieren, wenn sie abstürzen. Ich muss diese verwaisten tmp-Dateien löschen, sonst geht zukünftigen Prozessen der Speicherplatz auf /tmp aus.

Wie kann ich /tmp sicher entsorgen? Manche Leute tun dies, indem sie den Zeitstempel der letzten Änderung prüfen, aber dieser Ansatz ist unsicher, da es lang laufende Prozesse geben kann, die diese Dateien noch benötigen. Ein sichererer Ansatz besteht darin, die Bedingung des Zeitstempels der letzten Änderung mit der Bedingung zu kombinieren, dass kein Prozess einen Datei-Handle für die Datei hat. Gibt es ein Programm/Skript/usw., das diesen Ansatz oder einen anderen Ansatz verkörpert, der ebenfalls sicher ist?

Erlaubt Linux/Unix übrigens einen Modus zum Öffnen und Erstellen von Dateien, bei dem die erstellte Datei gelöscht wird, wenn der Erstellungsprozess beendet wird, selbst wenn dies durch einen Absturz geschieht?

Antwort1

Vielleicht möchten Sie so etwas versuchen:

find /tmp -mtime +7 -and -not -exec fuser -s {} ';' -and -exec echo {} ';'

Mit „find“ werden Dateien gesucht, die bestimmten Kriterien entsprechen.

  • -mtime +7wählt nur Dateien aus, die älter als 7 Tage sind (Sie können jeden anderen Wert verwenden)
  • -exec fuser -s {} ';'ruft fuser im stillen Modus für jede Datei auf, die das Alterkriterium erfüllt. fuser gibt 0 (=true) für jede Datei zurück, auf die gerade zugegriffen wurde, und 1 (=false) für die nicht zugegriffenen Dateien. Da wir nur an den nicht zugegriffenen Dateien interessiert sind, setzen wir ein -notvoran-exec
  • -exec echo {} ';'druckt einfach alle Dateinamen, die den Kriterien entsprechen. Vielleicht möchten Sie -exec rm {} ';'hier stattdessen „use“ verwenden, aber da dadurch möglicherweise einige noch verwendete Dateien gelöscht werden, halte ich es für sicherer, zuerst ein einfaches „echo“ auszuführen.
  • bearbeiten:Möglicherweise möchten Sie etwas wie hinzufügen -name 'foo*.bar'oder -uid 123die Auswirkungen der Bereinigung auf bestimmte Dateimuster oder Benutzer-IDs beschränken, um unbeabsichtigte Auswirkungen zu vermeiden.

Zum letzten Punkt: Bedenken Sie, dass es Dateien geben könnte, die nur einmal geschrieben werden (z. B. beim Systemstart), aber häufig gelesen werden (z. B. jedes X-Session-Cookie). Daher empfehle ich, einige Namensprüfungen hinzuzufügen, um nur Dateien zu beeinflussen, die von Ihren fehlerhaften Programmen erstellt wurden.

Bearbeitung2: Zu Ihrer letzten Frage: Eine Datei wird erst dann von der Festplatte gelöscht, wenn kein Prozess einen offenen Handle dafür hat (zumindest bei nativen Linux-Dateisystemen). Das Problem ist, dass der Verzeichniseintrag sofort entfernt wird, was bedeutet, dass ab dem Zeitpunkt, an dem Sie die Datei entfernen, kein neuer Prozess die Datei mehr öffnen kann (da kein Dateiname daran angehängt ist).

Einzelheiten finden Sie unter: https://stackoverflow.com/questions/3181641/wie-kann-ich-eine-datei-nach-ihrer-schließung-in-c-on-linux-löschen

Bearbeitung3:Aber was wäre, wenn ich den gesamten Prozess automatisieren wollte?

Wie gesagt, es gibt möglicherweise Dateien, die einmal geschrieben und dann ab und zu gelesen werden (z. B. X-Session-Cookies, PID-Dateien usw.). Diese werden von diesem kleinen Entfernungsskript nicht ausgeschlossen (weshalb Sie möglicherweise zuerst einen Testlauf durchführen möchten, echobevor Sie Dateien tatsächlich löschen).

Eine Möglichkeit, eine sichere Lösung zu implementieren, ist die Verwendung von atime.
atimespeichert die Zeit, zu der jede Datei zuletzt aufgerufen wurde. Diese Dateisystemoption wird jedoch häufig deaktiviert, da sie erhebliche Auswirkungen auf die Leistung hat (lautdieser Blogirgendwo im Bereich von 20–30 %). Es gibt relatime, aber dieses schreibt nur die Zugriffszeit, wenn mtimesie sich geändert hat, also wird uns dieses nicht helfen.

Wenn Sie verwenden möchten atime, empfehle ich die Verwendung /tmpeiner separaten Partition (idealerweise einer Ramdisk), damit die Leistungseinbußen für das gesamte System nicht zu groß sind.

Sobald aktiviert ist, müssen Sie nur noch den Parameter in der obigen Befehlszeile durch atimeersetzen . Sie können das möglicherweise entfernen , aber ich würde es zur Sicherheit dort lassen (falls Anwendungen Dateien für längere Zeit geöffnet halten).-mtime-atime
-not -exec fuser -s {} ';'

Denken Sie jedoch daran, den Befehl zu testen, echobevor Sie Dinge entfernen, die Ihr System noch benötigt!

Antwort2

Drehen Sie nicht Ihr eigenes Zeug.

Debian/Ubuntu haben tmpreaper, es ist wahrscheinlich auch in anderen Distributionen verfügbar.

# tmpreaper - cleans up files in directories based on their age

sudo apt-get install tmpreaper

cat /etc/tmpreaper.conf 

Antwort3

Zum letzten Teil Ihrer Frage:

Obwohl ich nicht glaube, dass es einen Öffnungs-/Erstellungsmodus gibt, bei dem man dies löscht, wenn man stirbt, kann ein Prozess eine Datei direkt nach ihrer Erstellung sicher löschen, solange er einen Handle für die besagte Datei offen hält. Der Kernel behält die Datei dann auf der Festplatte und sobald der letzte Prozess, der die Datei geöffnet hat, beendet wird (sei es durch Absturz oder normal), wird der von der Datei belegte Speicherplatz freigegeben.

Um das Problem, dass manche Prozesse /tmp manchmal nicht bereinigen, zu umgehen, empfehle ich einen Blick auf die Mount-Namespaces, die beispielsweise beschrieben werdenHieroderHierHandelt es sich bei dem betreffenden Prozess um einen System-Daemon,systemdund seine native Funktion, private /tmp-Dateisysteme zuzulassen, könnte von Interesse sein.

Antwort4

Erhalten Sie eine Liste mit Dateien, die älter sind als so und so, und schließen Sie Dateien aus der Liste aus, die mit irgendetwas geöffnet werden:

find /tmp -mtime +7 |\
    egrep -v "`lsof -n +D /tmp | awk 'NR>1 {print $9}'| tr \\n \|`" 

lsof -n +D /tmp: nach offenen Dateien in /tmp suchen
awk 'NR>1 {print $9}': nur die neunte Spalte der lsof-Ausgabe drucken, ohne die Kopfzeilen
tr \\n \|: neue Zeile durch bar ersetzen (ODER in egrep)
egrep -v "foo|moo|bar": Zeilen drucken, die NICHT foo oder moo oder bar enthalten

verwandte Informationen