Ich erstelle temporäre Dateien aus einem Bash-Skript. Ich lösche sie am Ende der Verarbeitung, aber da das Skript ziemlich lange läuft, werden die temporären Dateien nicht gelöscht, wenn ich es während des Laufs töte oder einfach STRG-C.
Gibt es eine Möglichkeit, diese Ereignisse abzufangen und die Dateien zu bereinigen, bevor die Ausführung endet?
Gibt es auch eine bewährte Methode für die Benennung und den Speicherort dieser temporären Dateien?
Ich bin mir derzeit nicht sicher, ob ich Folgendes verwenden soll:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
und
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
Oder gibt es vielleicht bessere Lösungen?
bash
exit
temporary-files
skinp
quelle
quelle
Antworten:
Sie können eine " Falle " festlegen , die beim Beenden ausgeführt wird, oder eine Steuerung-c, um sie zu bereinigen.
Alternativ besteht einer meiner Lieblings-Unix-Ismen darin, eine Datei zu öffnen und sie dann zu löschen, während Sie sie noch geöffnet haben. Die Datei bleibt im Dateisystem und Sie können sie lesen und schreiben. Sobald Ihr Programm beendet wird, verschwindet die Datei. Ich bin mir jedoch nicht sicher, wie Sie das in Bash machen würden.
Übrigens: Ein Argument, das ich für mktemp geben werde, anstatt Ihre eigene Lösung zu verwenden: Wenn der Benutzer erwartet, dass Ihr Programm große temporäre Dateien erstellen wird, möchte er möglicherweise einen
TMPDIR
größeren Ort wie / var / tmp festlegen . mktemp erkennt, dass Ihre handgerollte Lösung (zweite Option) dies nicht tut. Ich benutzeTMPDIR=/var/tmp gvim -d foo bar
zum Beispiel häufig.quelle
exec 5<>$TMPFILE
5 Bindungen Dateideskriptors TMPFILE als Schreib-Lese-Dollar, und Sie verwenden können<&5
,>&5
und/proc/$$/fd/5
(Linux) danach. Das einzige Problem ist, dass Bash keineseek
Funktion hat ...trap
: Es gibt keine Möglichkeit zum EinfangenSIGKILL
(beabsichtigt, da die Ausführung sofort beendet wird). Wenn dies passieren könnte, haben Sie einen Fallback-Plan (z. B.tmpreaper
). Zweitens sind Traps nicht kumulativ. Wenn Sie mehr als eine Aktion ausführen müssen, müssen sie alle imtrap
Befehl enthalten sein. Eine Möglichkeit, mit mehreren Bereinigungsaktionen umzugehen, besteht darin, eine Funktion zu definieren (und Sie können sie bei Bedarf im Verlauf Ihres Programms neu definieren) und darauf zu verweisen :trap cleanup_function EXIT
.trap "rm -f $LOCKFILE" EXIT
oder ich würde einen unerwarteten Fehler am Ende der Datei bekommen.Normalerweise erstelle ich ein Verzeichnis, in dem alle meine temporären Dateien abgelegt werden sollen, und erstelle anschließend einen EXIT-Handler, um dieses Verzeichnis beim Beenden des Skripts zu bereinigen.
Wenn Sie alle Ihre temporären Dateien unter ablegen
$MYTMPDIR
, werden sie alle gelöscht, wenn Ihr Skript in den meisten Fällen beendet wird. Wenn Sie einen Prozess mit SIGKILL (kill -9) beenden, wird der Prozess jedoch sofort beendet, sodass Ihr EXIT-Handler in diesem Fall nicht ausgeführt wird.quelle
Sie möchten den Befehl trap verwenden , um das Beenden des Skripts oder von Signalen wie STRG-C zu handhaben. Weitere Informationen finden Sie im Greg's Wiki .
Für Ihre temporären Dateien ist die Verwendung
basename $0
eine gute Idee sowie die Bereitstellung einer Vorlage, die Platz für genügend temporäre Dateien bietet:quelle
tempfile
Befehl, während alle vernünftigen modernen Systeme, die ich kenne, einenmktemp
Befehl haben.Denken Sie daran, dass die gewählte Antwort lautet
bashism
, was Lösung als bedeutetwürde nur in bash funktionieren (es wird Strg + c nicht abfangen, wenn Shell
dash
oder klassisch istsh
), aber wenn Sie Kompatibilität wünschen, müssen Sie immer noch alle Signale auflisten, die Sie abfangen möchten.Denken Sie auch daran, dass beim Beenden des Skripts die Falle für das Signal "0" (auch bekannt als EXIT) immer ausgeführt wird, was zu einer doppelten Ausführung des
trap
Befehls führt.Das ist der Grund, nicht alle Signale in einer Zeile zu stapeln, wenn es ein EXIT-Signal gibt.
Zum besseren Verständnis sehen Sie sich das folgende Skript an, das ohne Änderungen auf verschiedenen Systemen funktioniert:
Diese Lösung gibt Ihnen mehr Kontrolle, da Sie einen Teil Ihres Codes beim Auftreten des tatsächlichen Signals kurz vor dem endgültigen Beenden (
preExit
Funktion) ausführen können und bei Bedarf Code beim tatsächlichen EXIT-Signal (letzte Stufe des Beenden) ausführen können.quelle
Die Alternative, einen vorhersehbaren Dateinamen mit $$ zu verwenden, ist eine klaffende Sicherheitslücke, und Sie sollten niemals daran denken, ihn zu verwenden. Auch wenn es sich nur um ein einfaches persönliches Skript auf Ihrem Einzelbenutzer-PC handelt. Es ist eine sehr schlechte Angewohnheit, die Sie nicht erhalten sollten. BugTraq ist voll von Vorfällen mit "unsicheren temporären Dateien". Weitere Informationen zum Sicherheitsaspekt von temporären Dateien finden Sie hier , hier und hier .
Ich dachte anfangs daran, die unsicheren TMP1- und TMP2-Zuweisungen zu zitieren, aber beim zweiten Gedanken wäre das wahrscheinlich keine gute Idee .
quelle
Ich bevorzuge die Verwendung
tempfile
einer Datei in / tmp auf sichere Weise, und Sie müssen sich keine Gedanken über deren Benennung machen:quelle
Ich kann nicht glauben, dass so viele Leute davon ausgehen, dass ein Dateiname kein Leerzeichen enthält. Die Welt wird abstürzen, wenn $ TMPDIR jemals einem "temporären Verzeichnis" zugewiesen wird.
Leerzeichen und andere Sonderzeichen wie einfache Anführungszeichen und Zeilenumbrüche in Dateinamen sollten im Code als Voraussetzung für eine angemessene Programmiergewohnheit betrachtet werden.
quelle
trap 'rm -f "${zTemp}"' EXIT
Leerzeichen und andere Sonderzeichen korrekt behandelt werden, verschiebt die Lösung dieser Antwort die Bewertung von nichtzTemp
. Sie müssen sich daher keine Gedanken darüber machen, welchen WertzTemp
es hat, später im Skript geändert zu werden. AuchzTemp
kann erklärt lokal für eine Funktion werden; Es muss keine globale Skriptvariable sein.${parameter@operator}
Erweiterungen in Bash 4.4 (veröffentlicht im September 2016) hinzugefügt wurden.Sie müssen sich nicht die Mühe machen, die mit mktemp erstellten tmp-Dateien zu entfernen. Sie werden später trotzdem gelöscht.
Verwenden Sie mktemp, wenn Sie können, da es mehr eindeutige Dateien als das Präfix '$$' generiert. Und es sieht nach einer plattformübergreifenden Methode aus, temporäre Dateien zu erstellen, als sie explizit in / tmp abzulegen.
quelle