So entfernen Sie zuverlässig alle in einem Skript erstellten temporären Dateien?

2368
kaligne

Ist es möglich, das Beenden / Zurückkehren einer Funktion abzufangen? Für ein Programm könnte ich das machen

trap -- "clean_this" EXIT 

Das würde die Funktion ausführen, clean_thiswenn das Programm beendet wird. Beim Verlassen einer Funktion möchte ich etwas Ähnliches tun.

function myfunc() { echo "I'm a function" }  myfunc & wait $! 

Ich führe die Funktion in einer Subshell aus, und ich möchte sie mit exit / return abfangen. Ist das möglich?


EDIT1

Hier ist mein Zweck

Ich habe ein Skript, das temporäre Dateien verwalten soll:

cat tempfiles.sh  ## List of temp files tmp_tmp_files=()  ## Adds a file to the list of temp files function tmp_add_file() { tmp_tmp_files+=("$1") }  ## Resets the list of temp files function tmp_reset_files() { tmp_tmp_files=() }  ## Removes the list of temp files  function tmp_rm_all() { rm -f "$" }  ## Removes all temp files on exit and sigint trap "tmp_rm_all" EXIT SIGINT 

Hier ist mein Hauptskript:

cat mscript.sh  source tempfiles.sh  ## ## Creates a temp file and writes in it mfunc() { local tempfile=$(mktemp) tmp_add_file $tempfile echo "something" >> $tempfile echo "($BASHPID) - tempfiles: $" }  ## Creates a temp file in main shell mfunc  ## Creates a temp file in a subshell (mfunc) 

Ich nenne das Hauptskript:

$ bash mscript.sh  (92250) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj (92254) - tempfiles: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq 

Ich überprüfe die temporären Dateien:

$ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj cat: /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.oRlUxEBj: No such file or directory  $ cat /var/folders/9k/h6hn75090_n8z0kythwmwqp96_0t2m/T/tmp.s1iIvtpq  something 

Die in deklarierten temporären Dateien subshellgehen beim Beenden des Programms aus der Liste verloren. Ich möchte sie am Ende der Funktion idealerweise entfernen lassen. Entweder muss ich sie vor dem Verlassen der Funktion gezielt entfernen, es ist einfach und kostet mich eine weitere Zeile:

mfunc() { local tempfile=$(mktemp) tmp_add_file $tempfile1 echo "something" >> $tempfile echo "tempfiles: $" ## Process things... rm $tempfile1 } 

Aber ich würde gerne wissen, ob es eine elegante Möglichkeit gibt, sie (die in den erstellten temporären Dateien subshells) automatisch zu entfernen, wie ich es trapbeim Beenden des Programms mit s mache .

Meine Frage ist also: Kann man das machen? Was könnten Alternativen sein?

0
Was willst du erreichen? Die in den Hintergrund gestellte Funktion kann eine andere Funktion aufrufen. Lassen Sie also myfunc `clean_this` ganz am Ende aufrufen. Oder rufen Sie sie wie ` & `. [Brauchen Sie wirklich eine Falle?] (Https://meta.stackexchange.com/a/66378/355310) Kamil Maciorowski vor 6 Jahren 0
Danke für Ihre Antwort. Hier habe ich meine Frage bearbeitet und meine Absicht geschrieben. Sicherlich kann ich Fallen vermeiden, aber seit ich damit angefangen habe, wenn ich tun kann, was ich will, auf einfache Weise ... Warum nicht? kaligne vor 6 Jahren 0

1 Antwort auf die Frage

1
Kamil Maciorowski

Subshells erben die Umgebung oder einen Teil davon. Es sieht so aus, als ob Sie beim Ausführen einer Funktion in einer Subshell Ihre Variablen nicht exportieren müssen (vergleiche: Beim Export von Funktionen in der Subshell ist kein Export erforderlich ). Es kann Fälle geben, in denen Sie etwas brauchen, exportaber konzentrieren wir uns auf Ihr Beispiel.

Ihr Ansatz ist fehlerhaft und wird schwer aufrechtzuerhalten, da Vererbung in eine Richtung geht. Jeder (mfunc)erbt tmp_tmp_filesund arbeitet mit einer eigenen Kopie des Arrays. Es ist unmöglich, das tmp_tmp_filesim Hauptskript verwendete Original zu ändern . Daher kann das Hauptskript nicht alles bereinigen, es verfügt einfach nicht über genügend Informationen.

Wenn Sie sich für die Bereinigung der untergeordneten Funktion entscheiden, müssen Sie darauf achten, dass die temporären Dateien der Funktion von den temporären Dateien des Hauptskripts unterschieden werden. Das vorzeitige Entfernen des letzteren kann dazu führen, dass Ihr Skript fehlschlägt.

Alternativer Ansatz: ein temporäres Verzeichnis

  1. Anstatt ein Array zu erstellen, erstellen Sie ein Verzeichnis und merken Sie sich dessen Pfad. Tun Sie es einmal am Anfang und exportwenn Sie brauchen:

    tempdir=$(mktemp -d mscript.XXXXXXXXXX) 
  2. Erstellen Sie jede temporäre Datei innerhalb des temporären Verzeichnisses wie folgt:

    tempfile=$(mktemp -p "$tempdir") 
  3. Entfernen Sie am Ende das gesamte Verzeichnis, unabhängig davon, ob die betreffenden Dateien vom Hauptskript oder von einer Subshell oder sogar von einem Fremdprogramm eines Fremdanbieters erstellt wurden. Sie können einen Trap verwenden, um diesen Schritt auszuführen. Einfach:

    rm -r "$tempdir" 
Danke, das mache ich jetzt. Ich nehme an, es gibt keine Möglichkeit, etwas auszulösen, sobald eine Funktion aufhört. Recht? kaligne vor 6 Jahren 0
@ user3298319 Ich weiß es nicht genau. So geschah es, dass Ihre Frage das [XY-Problem] war (https://meta.stackexchange.com/a/66378/355310) und ich antwortete, um Ihr aktuelles Problem zu lösen. Ich habe auch den Titel geändert und ist daher für Benutzer, die an Traps interessiert sind, nicht nützlich. es ist nützlich bei temporären Dateien. Mein Punkt ist: Diese Frage hat sich entwickelt. Wenn Sie Fallen erforschen möchten, können Sie eine andere Frage stellen und dort erklären, dass Sie aus Neugierde fragen. Dies wird jedoch möglicherweise nicht gut angenommen. Die Website konzentriert sich auf die Lösung praktischer Probleme, und die Benutzer geben Ihnen die richtigen Werkzeuge wie ich. Kamil Maciorowski vor 6 Jahren 0