Temporäre Dateien in Bash erstellen

150

Gibt es objektiv bessere Möglichkeiten, temporäre Dateien in Bash-Skripten zu erstellen?

Normalerweise benenne ich sie einfach, was mir in den Sinn kommt, wie z. B. tempfile-123, da es gelöscht wird, wenn das Skript beendet ist. Gibt es einen anderen Nachteil, als ein mögliches tempfile-123 im aktuellen Ordner zu überschreiben? Oder hat es einen Vorteil, eine temporäre Datei sorgfältiger zu erstellen?

Strapakowsky
quelle
1
Verwenden Sie keine temporären Dateien. Verwenden Sie stattdessen zeitliche Verzeichnisse. Und benutze kein mktemp. Sehen Sie hier, warum: codeproject.com/Articles/15956/…
ceving
17
@ceving Dieser Artikel ist einfach falsch, zumindest wenn er auf den Shell-Befehl mktemp angewendet wird (im Gegensatz zum Aufruf der mktemp-Bibliothek). Da mktemp die Datei selbst mit einer restriktiven Umask erstellt, funktioniert der angegebene Angriff nur, wenn der Angreifer unter demselben Konto wie der Angreifer arbeitet. In diesem Fall ist das Spiel bereits verloren. Best Practices in der Shell-Scripting-Welt finden Sie unter mywiki.wooledge.org/BashFAQ/062
Charles Duffy
Sie können es auch tempfile(1)auf Systemen verwenden, auf denen es vorhanden ist.
Bis auf weiteres angehalten.

Antworten:

179

Die mktemp(1)Manpage erklärt es ziemlich gut:

Traditionell verwenden viele Shell-Skripte den Namen des Programms mit der PID als Suffix und verwenden diesen als temporären Dateinamen. Diese Art von Namensschema ist vorhersehbar und die damit verbundenen Rennbedingungen sind für einen Angreifer leicht zu gewinnen. Ein sicherer, wenn auch immer noch minderwertiger Ansatz besteht darin, ein temporäres Verzeichnis mit demselben Namensschema zu erstellen. Auf diese Weise kann zwar garantiert werden, dass eine temporäre Datei nicht untergraben wird, es ist jedoch ein einfacher Denial-of-Service-Angriff möglich. Aus diesen Gründen wird empfohlen, stattdessen mktemp zu verwenden.

In einem Skript rufe ich so etwas wie mktemp auf

mydir=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")

Dadurch wird ein temporäres Verzeichnis erstellt, in dem ich arbeiten kann, und in dem ich den tatsächlichen Dateien sicher etwas Lesbares und Nützliches geben kann.

mktempist kein Standard, existiert aber auf vielen Plattformen. Die "X" werden im Allgemeinen in eine gewisse Zufälligkeit umgewandelt, und mehr werden wahrscheinlich zufälliger sein; Einige Systeme (zum Beispiel Busybox-Asche) begrenzen diese Zufälligkeit jedoch stärker als andere


Übrigens ist die sichere Erstellung temporärer Dateien nicht nur für Shell-Skripte wichtig. Deshalb hat Python Tempfile , Perl File :: Temp , Ruby Tempfile usw.

Kojiro
quelle
1
Die Option -t ist veraltet: gnu.org/software/coreutils/manual/html_node/…
Tibor Vass
7
Es scheint, dass die sicherste und plattformübergreifendste Art der Verwendung mktempin Kombination mit einer basenamesolchen ist mktemp -dt "$(basename $0). XXXXXXXXXX". Bei Verwendung ohne basenamediese Meldung wird möglicherweise eine Fehlermeldung wie die folgende angezeigt: mtemp: ungültige Vorlage "/tmp/MOB-SAN-JOB1-183-ScriptBuildTask-7300464891856663368.sh.XXXXXXXXXX" enthält ein Verzeichnistrennzeichen .
i4niac
7
Ignorieren Sie sie Tippfehler (zusätzlicher Platz). mktemp -dt "$(basename $0).XXXXXXXXXX"ist der richtige Weg.
i4niac
3
@ i4niac: Sie müssen das zitieren $0, es gibt viele Räume im Land von OS X.mktemp -dt "$(basename "$0").XXXXXX"
Orwellophile
11
Es kann auch schön sein, das Tempdir am Ende der Skriptausführung zu entfernen:trap "rm -rf $mydir" EXIT
KumZ
43

Ja, benutze mktemp .

Es wird eine temporäre Datei in einem Ordner erstellt, in dem temporäre Dateien gespeichert werden, und es wird Ihnen ein eindeutiger Name garantiert. Es gibt den Namen dieser Datei aus:

> mktemp
/tmp/tmp.xx4mM3ePQY
>
Paul
quelle
19

Vielleicht möchten Sie sich ansehen mktemp

Das Dienstprogramm mktemp verwendet die angegebene Dateinamenvorlage und überschreibt einen Teil davon, um einen eindeutigen Dateinamen zu erstellen. Die Vorlage kann ein beliebiger Dateiname sein, an den eine bestimmte Anzahl von 'X' angehängt ist, z. B. /tmp/tfile.XXXXXXXXXX. Die nachfolgenden 'X' werden durch eine Kombination aus der aktuellen Prozessnummer und zufälligen Buchstaben ersetzt.

Für weitere Details: man mktemp

John Lawrence
quelle
11

Gibt es einen Vorteil bei der sorgfältigeren Erstellung einer temporären Datei?

Die temporären Dateien werden normalerweise in dem temporären Verzeichnis (z. B. /tmp) erstellt, in dem alle anderen Benutzer und Prozesse Lese- und Schreibzugriff haben (jedes andere Skript kann die neuen Dateien dort erstellen). Daher sollte das Skript beim Erstellen der Dateien vorsichtig sein, z. B. mit den richtigen Berechtigungen (z. B. schreibgeschützt für den Eigentümer, siehe help umask:)), und der Dateiname sollte nicht leicht zu erraten sein (idealerweise zufällig). Wenn die Dateinamen nicht eindeutig sind, kann dies zu Konflikten mit demselben Skript führen, das mehrmals ausgeführt wurde (z. B. Race-Bedingung)) oder ein Angreifer könnte entweder vertrauliche Informationen entführen (z. B. wenn die Berechtigungen zu offen sind und der Dateiname leicht zu erraten ist) oder die Datei durch eine eigene Version des Codes erstellen / ersetzen (z. B. das Ersetzen der Befehle oder SQL-Abfragen, je nachdem, was gerade ist) gelagert).


Sie können den folgenden Ansatz verwenden, um das temporäre Verzeichnis zu erstellen:

TMPDIR=".${0##*/}-$$" && mkdir -v "$TMPDIR"

oder temporäre Datei:

TMPFILE=".${0##*/}-$$" && touch "$TMPFILE"

Es ist jedoch immer noch vorhersehbar und wird nicht als sicher angesehen.

Laut man mktempkönnen wir lesen:

Traditionell verwenden viele Shell-Skripte den Namen des Programms mit der PID als Suffix und verwenden diesen als temporären Dateinamen. Diese Art von Namensschema ist vorhersehbar und die damit verbundenen Rennbedingungen sind für einen Angreifer leicht zu gewinnen.

Aus Sicherheitsgründen wird empfohlen, den mktempBefehl zum Erstellen einer eindeutigen temporären Datei oder eines eindeutigen Verzeichnisses ( -d) zu verwenden.

Kenorb
quelle
2
nicht genau das, was gefragt wurde. Es kann jedoch eine perfekte Lösung sein.
Jpbochi
1
@jpbochi Ich habe die Antwort verbessert, um die Frage zu beantworten. Lassen Sie mich wissen, ob das hilft.
Kenorb
2
Es verbessert tatsächlich die Antwort. Meine Gegenstimme war jedoch bereits deine. Kann nicht mehr abstimmen. Ein Vorschlag, den ich habe, ist zu erklären, was ${0##*/}und zu $$erweitern oder auf eine Dokumentation darüber zu verlinken.
Jpbochi
0

mktemp ist wahrscheinlich die vielseitigste, insbesondere wenn Sie vorhaben, eine Weile mit der Datei zu arbeiten.

Sie können auch einen Prozessersetzungsoperator verwenden, <() wenn Sie die Datei nur vorübergehend als Eingabe für einen anderen Befehl benötigen, z.

$ diff <(echo hello world) <(echo foo bar)
Barry Jones
quelle