Antworten:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Sie können sicherstellen, dass eine Datei gelöscht wird, wenn das Skript beendet wird (einschließlich Abbrüchen und Abstürzen), indem Sie einen Dateideskriptor für die Datei öffnen und diese löschen. Die Datei bleibt verfügbar (für das Skript; nicht wirklich für andere Prozesse, /proc/$PID/fd/$FD
ist aber ein Workaround), solange der Dateideskriptor geöffnet ist. Wenn es geschlossen wird (was der Kernel automatisch tut, wenn der Prozess beendet wird), löscht das Dateisystem die Datei.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
- außer für Systeme, die es nicht haben.
exec 3> "$tmpfile"
tun? Ist das nicht nur dann sinnvoll, wenn es sich bei der tmpfile um ein eigenständiges Skript handelt?
cat <&3
wird geben Bad file descriptor
. Ich würde es begrüßen, wenn Sie es entweder reparieren oder entfernen; Fehlinformationen helfen nicht viel.
Verwenden Sie mktemp
diese Option , um eine temporäre Datei oder ein temporäres Verzeichnis zu erstellen:
temp_file=$(mktemp)
Oder für ein Direcotry:
temp_dir=$(mktemp -d)
Am Ende des Skripts müssen Sie die temporäre Datei / dir löschen:
rm ${temp_file}
rm -R ${temp_dir}
mktemp erstellt eine Datei im /tmp
Verzeichnis oder in der mit dem --tmpdir
Argument angegebenen Verzeichnisstruktur .
trap "rm -f $temp_file" 0 2 3 15
direkt nach dem Erstellen der Datei verwenden, so dass beim Beenden des Skripts oder beim Stoppen ctrl-C
die Datei weiterhin entfernt wird.
EXIT
der einzige Haken dafür ist trap
?
kill -9 $somepid
. Dieses besondere Kill-Signal ist Insta-Death, und nichts anderes passiert.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
ist genug.
Wenn Sie sich auf einem System mit mktemp befinden , sollten Sie es als andere Antwort verwenden.
Mit POSIX-Werkzeugkasten:
umask 0177
tmpfile=/tmp/"$0"."$$"."$(awk 'BEGIN {srand();printf "%d\n", rand() * 10^10}')"
trap 'rm -f -- "$tmpfile"' INT TERM HUP EXIT
: > "$tmpfile"
EXIT
der einzige Haken für ist trap
?
tmpfile
vor dem Beenden des Skripts noch entfernt, aber nicht, wenn das Skript andere Signale empfangen hat.
That's not what happens
?
mktemp
entstanden in HP / UX mit einer anderen Syntax. Todd C. Miller hat Mitte der 90er Jahre eine andere Version für OpenBSD entwickelt (kopiert von FreeBSD und NetBSD) und später auch als eigenständiges Hilfsprogramm zur Verfügung gestellt (www.mktemp.org). Dies war diejenige, die normalerweise unter Linux verwendet wurde, bis 2007 ein (größtenteils kompatibles) mktemp
Dienstprogramm zu den GNU-Coreutils hinzugefügt wurde mktemp
.
Einige Shells haben die Funktion eingebaut.
zsh
Die =(...)
Form der Prozessersetzung verwendet eine temporäre Datei. Erweitert beispielsweise =(echo test)
den Pfad einer temporären Datei, die enthält test\n
.
$ {cat $file; ls -l /dev/fd/3; echo test2 >&3; cat $file} 3<> ${file::==(echo test)}
test
lrwx------ 1 stephane stephane 64 Jan 30 11:19 /dev/fd/3 -> /tmp/zshMLbER0
test2
Diese Datei wird nach Beendigung des Befehls automatisch entfernt.
Here-Dateien oder Here-Strings in bash
und zsh
werden als gelöschte temporäre Dateien implementiert.
Also wenn du tust:
exec 3<<< test
Der Dateideskriptor 3 ist mit einer gelöschten temporären Datei verbunden, die enthält test\n
.
Sie können den Inhalt erhalten mit:
cat <&3
Unter Linux können Sie diese Datei auch über lesen oder schreiben /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(Einige andere Shells verwenden Pipes oder können verwendet werden, /dev/null
wenn das Dokument hier leer ist.)
Es gibt kein mktemp
POSIX-Dienstprogramm. POSIX gibt jedoch eine mkstemp(template)
C-API an , und das m4
Standarddienstprogramm macht diese API mit der gleichnamigen mkstemp()
m4-Funktion verfügbar.
mkstemp()
gibt Ihnen einen Dateinamen mit einem zufälligen Teil, der zum Zeitpunkt des Funktionsaufrufs garantiert nicht vorhanden war. Es erstellt die Datei mit den Berechtigungen 0600 auf rennfreie Weise.
Sie könnten also Folgendes tun:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Beachten Sie jedoch, dass Sie die Bereinigung beim Beenden durchführen müssen. Wenn Sie die Datei jedoch nur eine feste Anzahl von Malen schreiben und lesen müssen, können Sie sie direkt nach dem Erstellen öffnen und löschen, z. B. für here-doc / here-. String-Ansatz oben:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
# open once for writing, twice for reading:
exec 3> "$tempfile" 4< "$tempfile" 5< "$tempfile"
rm -f -- "$tmpfile"
cmd >&3 # store something in the temp file
exec 3>&- # fd no longer needed
# read the content twice:
cat <&4
cat <&5
Sie können die Datei zum Lesen einmal öffnen und zwischen zwei Lesevorgängen zurückspulen. Es gibt jedoch kein POSIX-Dienstprogramm, das das Zurückspulen durchführen kann ( lseek()
). Sie können es also nicht portabel in einem POSIX-Skript ( zsh
( sysseek
eingebaut) und ksh93
( <#((...))
Operator) ausführen mach es aber).
<()
=(...)
.
Hier ist eine etwas verbesserte Antwort in der Zeile von Hauke Laging:
#!/bin/bash
tmpfile=$(mktemp) # Create a temporal file in the default temporal folder of the system
# Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
exec {FD_W}>"$tmpfile" # Create file descriptor for writing, using first number available
exec {FD_R}<"$tmpfile" # Create file descriptor for reading, using first number available
rm "$tmpfile" # Delete the file, but file descriptors keep available for this script
# Now it is possible to work with the temporal file
echo foo >&$FD_W
echo bar >&$FD_W # Note that file descriptor always concatenates, not overwrites
cat <&$FD_R
Mein Workflow mit temporären Dateien basiert normalerweise auf einem Bash-Skript, das ich teste. Ich möchte tee
es öffnen, damit ich sehen kann, dass es funktioniert, und die Ausgabe für die nächste Iteration meines Prozesses speichern. Ich habe eine Datei namens erstellttmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
damit ich es gerne nutzen kann
$ some_command --with --lots --of --stuff | tee $(tmp)
Der Grund, warum ich die vor den Zufallswerten formatierte Datumszeit mag, ist, dass ich die soeben erstellte tmp-Datei leicht finden kann und nicht darüber nachdenken muss, wie ich sie das nächste Mal benennen soll (und mich darauf konzentrieren muss, nur mein Dang-Skript abzurufen arbeiten).