Membuat file sementara di bash

150

Apakah ada cara yang lebih baik secara obyektif untuk membuat file sementara di skrip bash?

Saya biasanya hanya memberi nama mereka apa pun yang muncul di pikiran saya, seperti tempfile-123, karena itu akan dihapus ketika skrip selesai. Apakah ada kerugian dalam melakukan ini selain menimpa tempfile-123 yang mungkin di folder saat ini? Atau adakah keuntungan dalam membuat file sementara dengan cara yang lebih hati-hati?

Strapakowsky
sumber
1
Jangan gunakan file sementara. Gunakan direktori sementara sebagai gantinya. Dan jangan gunakan mktemp. Lihat di sini mengapa: codeproject.com/Articles/15956/...
ceving
17
@ceving Artikel itu benar-benar salah, setidaknya ketika diterapkan pada perintah shell mktemp (sebagai lawan dari panggilan pustaka mktemp). Saat mktemp membuat file itu sendiri dengan umask terbatas, serangan yang diberikan hanya berfungsi jika penyerang beroperasi di bawah akun yang sama dengan penyerang ... dalam hal ini gim tersebut sudah hilang. Untuk praktik terbaik di dunia skrip shell, lihat mywiki.wooledge.org/BashFAQ/062
Charles Duffy
Anda juga dapat menggunakan tempfile(1)pada sistem yang memilikinya.
Dijeda sampai pemberitahuan lebih lanjut.

Jawaban:

179

The mktemp(1)man page menjelaskan dengan cukup baik:

Secara tradisional, banyak skrip shell menggunakan nama program dengan pid sebagai suffix dan menggunakannya sebagai nama file sementara. Skema penamaan semacam ini dapat diprediksi dan kondisi balapan yang dibuatnya mudah bagi penyerang untuk menang. Pendekatan yang lebih aman, meskipun masih lebih rendah, adalah membuat direktori sementara menggunakan skema penamaan yang sama. Meskipun hal ini memungkinkan seseorang untuk menjamin bahwa file sementara tidak akan ditumbangkan, itu masih memungkinkan penolakan serangan layanan sederhana. Untuk alasan ini disarankan agar mktemp digunakan sebagai gantinya.

Dalam sebuah skrip, saya memanggil sesuatu seperti mktemp

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

yang membuat direktori sementara saya dapat bekerja, dan di mana saya dapat dengan aman memberi nama file aktual sesuatu yang dapat dibaca dan berguna.

mktempbukan standar, tetapi ada pada banyak platform. "X" umumnya akan dikonversi menjadi beberapa keacakan, dan lebih banyak mungkin akan lebih acak; Namun, beberapa sistem (busybox ash, untuk satu) membatasi keacakan ini lebih signifikan daripada yang lain


Omong-omong, pembuatan file sementara yang aman penting untuk lebih dari sekadar skrip shell. Itu sebabnya python memiliki tempfile , perl memiliki File :: Temp , ruby ​​memiliki Tempfile , dll ...

kojiro
sumber
1
Opsi -t tidak digunakan lagi: gnu.org/software/coreutils/manual/html_node/…
Tibor Vass
7
Tampaknya cara yang paling aman dan paling lintas platform untuk digunakan mktempadalah kombinasi dengan basename, seperti itu mktemp -dt "$(basename $0). XXXXXXXXXX". Jika digunakan tanpa basenameAnda mungkin mendapatkan kesalahan seperti mktemp ini : templat yang tidak valid, `/tmp/MOB-SAN-JOB1-183-ScriptBuildTask-7300464891856663368.sh.XXXXXXXXXX '', mengandung pemisah direktori .
i4niac
7
Abaikan mereka salah ketik (ruang ekstra). mktemp -dt "$(basename $0).XXXXXXXXXX"adalah cara yang benar.
i4niac
3
@ i4niac: Anda perlu mengutip itu $0, ada banyak ruang di tanah OS X.mktemp -dt "$(basename "$0").XXXXXX"
Orwellophile
11
Mungkin juga bagus untuk menghapus tempdir pada akhir eksekusi skrip:trap "rm -rf $mydir" EXIT
KumZ
43

Ya, gunakan mktemp .

Ini akan membuat file sementara di dalam folder yang dirancang untuk menyimpan file sementara, dan itu akan menjamin Anda nama yang unik. Ini menampilkan nama file itu:

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

Anda mungkin ingin melihatnya mktemp

Utilitas mktemp mengambil templat nama file yang diberikan dan menimpa sebagian untuk membuat nama file unik. Templat dapat berupa nama file apa pun dengan sejumlah 'Xs' yang ditambahkan, misalnya /tmp/tfile.XXXXXXXXXXX. Huruf 'X' yang tertinggal diganti dengan kombinasi nomor proses saat ini dan huruf acak.

Untuk lebih jelasnya: man mktemp

John Lawrence
sumber
11

Apakah ada keuntungan dalam membuat file sementara dengan cara yang lebih hati-hati

File sementara biasanya dibuat di direktori sementara (seperti /tmp) di mana semua pengguna dan proses lain memiliki akses baca dan tulis (skrip lain apa pun dapat membuat file baru di sana). Oleh karena itu skrip harus berhati-hati dalam membuat file seperti menggunakan dengan izin yang tepat (misalnya hanya baca untuk pemilik, lihat help umask:) dan nama file tidak mudah ditebak (idealnya acak). Kalau tidak, jika nama file tidak unik, itu dapat membuat konflik dengan skrip yang sama berjalan beberapa kali (misalnya kondisi balapan) atau penyerang dapat membajak beberapa informasi sensitif (misalnya ketika izin terlalu terbuka dan nama file mudah ditebak) atau membuat / mengganti file dengan versi kode mereka sendiri (seperti mengganti perintah atau pertanyaan SQL tergantung pada apa yang sedang disimpan).


Anda bisa menggunakan pendekatan berikut untuk membuat direktori sementara:

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

atau file sementara:

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

Namun itu masih bisa ditebak dan tidak dianggap aman.

Sesuai man mktemp, kita dapat membaca:

Secara tradisional, banyak skrip shell menggunakan nama program dengan pid sebagai suffix dan menggunakannya sebagai nama file sementara. Skema penamaan semacam ini dapat diprediksi dan kondisi balapan yang dibuatnya mudah bagi penyerang untuk menang.

Jadi agar aman, disarankan untuk menggunakan mktempperintah untuk membuat file atau direktori sementara yang unik ( -d).

kenorb
sumber
2
tidak persis apa yang diminta. Namun, itu bisa menjadi solusi yang sempurna.
jpbochi
1
@ jpbochi Saya telah meningkatkan jawaban untuk menjawab pertanyaan ini. Beri tahu saya jika itu membantu.
kenorb
2
Itu memang meningkatkan jawabannya. Namun, upvote saya sudah menjadi milik Anda. Tidak dapat memberikan suara lebih banyak. Satu saran yang saya miliki adalah menjelaskan apa ${0##*/}dan $$memperluas ke, atau tautan ke beberapa dokumentasi tentang hal itu.
jpbochi
0

mktemp mungkin yang paling serbaguna, terutama jika Anda berencana untuk bekerja dengan file untuk sementara waktu.

Anda juga dapat menggunakan operator substitusi proses <() jika Anda hanya perlu file sementara sebagai input ke perintah lain, misalnya:

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