Jawaban:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Anda dapat memastikan bahwa sebuah file dihapus ketika skrip keluar (termasuk kill dan crash) dengan membuka deskriptor file ke file dan menghapusnya. File tetap tersedia (untuk skrip; tidak benar-benar untuk proses lain tetapi /proc/$PID/fd/$FD
dapat diselesaikan) selama deskriptor file terbuka. Ketika itu ditutup (yang kernel lakukan secara otomatis ketika proses keluar) filesystem menghapus file.
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
- Kecuali untuk sistem yang tidak memilikinya.
exec 3> "$tmpfile"
dilakukan? Bukankah itu hanya berguna jika tmpfile adalah skrip yang berdiri sendiri?
cat <&3
akan memberi Bad file descriptor
. Saya akan menghargai jika Anda memperbaikinya atau menghapusnya; informasi yang salah tidak banyak membantu.
Gunakan mktemp
untuk membuat file atau direktori sementara:
temp_file=$(mktemp)
Atau untuk direcotry:
temp_dir=$(mktemp -d)
Di akhir skrip Anda harus menghapus file / dir sementara:
rm ${temp_file}
rm -R ${temp_dir}
mktemp membuat file di /tmp
direktori atau di dalam drectory yang diberikan dengan --tmpdir
argumen.
trap "rm -f $temp_file" 0 2 3 15
tepat setelah membuat file sehingga ketika skrip keluar atau dihentikan dengan ctrl-C
file tersebut masih dihapus.
EXIT
hanya kait untuk trap
?
kill -9 $somepid
. Sinyal pembunuhan khusus itu adalah kematian tanpa kejadian lain.
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
sudah cukup.
Jika Anda menggunakan sistem yang memiliki mktemp , Anda harus menggunakannya sebagai jawaban lain.
Dengan POSIX toolchest:
umask 0177
tmpfile=/tmp/"$0"."$$"."$(awk 'BEGIN {srand();printf "%d\n", rand() * 10^10}')"
trap 'rm -f -- "$tmpfile"' INT TERM HUP EXIT
: > "$tmpfile"
EXIT
hanya kait untuk trap
?
tmpfile
masih bisa dihapus sebelum skrip keluar, tetapi tidak ketika skrip menerima sinyal lain.
That's not what happens
?
mktemp
berasal dari HP / UX dengan sintaks yang berbeda. Todd C. Miller menciptakan yang berbeda untuk OpenBSD pada pertengahan 90-an (disalin oleh FreeBSD dan NetBSD) dan kemudian membuatnya juga tersedia sebagai utilitas mandiri (www.mktemp.org). Itulah yang biasanya digunakan di Linux sampai mktemp
utilitas (kebanyakan yang kompatibel) ditambahkan ke GNU coreutils pada tahun 2007. Hanya untuk mengatakan orang tidak bisa benar-benar mengatakan mktemp
adalah utilitas GNU.
Beberapa shell memiliki fitur bawaan.
zsh
's =(...)
bentuk substitusi proses menggunakan file sementara. Misalnya =(echo test)
memperluas ke jalur file sementara yang berisi 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
File itu secara otomatis dihapus, setelah perintah selesai.
File di sini atau di sini-string di bash
dan zsh
diimplementasikan sebagai file sementara yang dihapus.
Jadi, jika Anda melakukannya:
exec 3<<< test
File descriptor 3 terhubung ke file sementara dihapus yang berisi test\n
.
Anda bisa mendapatkan kontennya dengan:
cat <&3
Jika di Linux, Anda juga dapat membaca atau menulis ke file itu melalui /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(beberapa kerang lain menggunakan pipa, atau dapat digunakan /dev/null
jika dokumen di sini kosong).
Tidak ada mktemp
utilitas POSIX. Namun POSIX menentukan mkstemp(template)
API C , dan m4
utilitas standar memperlihatkan API itu dengan mkstemp()
fungsi m4 dengan nama yang sama.
mkstemp()
memberi Anda nama file dengan bagian acak yang dijamin tidak ada pada saat fungsi dipanggil. Itu membuat file dengan izin 0600 dengan cara bebas ras.
Jadi, Anda bisa melakukan:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Namun perlu dicatat bahwa Anda perlu menangani pembersihan saat keluar, meskipun jika Anda hanya perlu menulis dan membaca file beberapa kali, Anda dapat membukanya dan menghapusnya setelah membuat seperti untuk di sini-doc / di sini- pendekatan string di atas:
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
Anda dapat membuka file untuk membaca sekali, dan memundurkan di antara dua bacaan, namun tidak ada utilitas POSIX yang dapat melakukan rewinding ( lseek()
), sehingga Anda tidak dapat melakukannya dengan mudah dalam skrip POSIX ( zsh
( sysseek
builtin) dan ksh93
( <#((...))
operator) dapat lakukan saja).
<()
=(...)
.
Berikut ini adalah jawaban yang sedikit lebih baik di jajaran 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
Alur kerja saya biasanya dengan file temp adalah karena beberapa skrip bash yang saya uji. Saya ingin tee
itu jadi saya bisa melihat itu berfungsi dan menyimpan output untuk iterasi selanjutnya dari proses saya. Saya telah membuat file bernamatmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
sehingga saya bisa menggunakannya seperti
$ some_command --with --lots --of --stuff | tee $(tmp)
Alasan saya menyukai datetime yang diformat sebelum nilai-nilai acak adalah ia memungkinkan saya menemukan file tmp yang baru saja saya buat dengan mudah, dan saya tidak perlu memikirkan apa nama untuk itu waktu berikutnya (dan fokus hanya pada mendapatkan skrip dang saya bekerja).