Shell Script mktemp, apa metode terbaik untuk membuat pipa bernama sementara?

30

Saya sadar yang terbaik untuk membuat file sementara dengan mktemp, tetapi bagaimana dengan pipa bernama?

Saya lebih suka hal-hal yang sesuai POSIX mungkin, tetapi hanya Linux yang dapat diterima. Menghindari Bashisme adalah satu-satunya kriteria sulit saya, ketika saya menulisdash .

JM Becker
sumber

Jawaban:

41
tmppipe=$(mktemp -u)
mkfifo -m 600 "$tmppipe"

Tidak seperti pembuatan file biasa, yang cenderung dibajak oleh file yang ada atau tautan simbolik, pembuatan pipa nama melalui mkfifoatau fungsi yang mendasarinya membuat file baru di tempat yang ditentukan atau gagal. Sesuatu seperti : >fooini tidak aman karena jika penyerang dapat memprediksi output mktempmaka penyerang dapat membuat file target untuk dirinya sendiri. Tetapi mkfifo fooakan gagal dalam skenario seperti itu.

Jika Anda membutuhkan portabilitas POSIX penuh, mkfifo -m 600 /tmp/myfifoaman terhadap pembajakan tetapi rentan terhadap penolakan layanan; tanpa akses ke generator nama file acak yang kuat, Anda perlu mengatur upaya coba lagi.

Jika Anda tidak peduli dengan masalah keamanan halus di sekitar file sementara, Anda dapat mengikuti aturan sederhana: membuat direktori pribadi, dan menyimpan semuanya di sana.

tmpdir=
cleanup () {
  if [ -n "$tmpdir" ] ; then rm -rf "$tmpdir"; fi
  if [ -n "$1" ]; then kill -$1 $$; fi
}
tmpdir=$(mktemp -d)
trap 'cleanup' EXIT
trap 'cleanup HUP' HUP
trap 'cleanup TERM' TERM
trap 'cleanup INT' INT
mkfifo "$tmpdir/pipe"
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Saya sebenarnya sudah memilih ini sebagai solusi saya kemarin kemarin, saya sedang menunggu untuk melihat apakah seseorang mempostingnya, atau yang lebih baik. Saya juga merasa dir adalah cara untuk pergi, dalam kasus saya. Apapun ... Terima kasih atas bantuannya, saya menghargainya.
JM Becker
1
Bukankah seharusnya perintah jebakan itu trap "rm -rf '$tempdir'" EXIT HUP INT TERM? Bisakah menjebak melakukan ekspansi variabel itu sendiri?
Enam
@Six Perintah Anda akan diperluas $tempdirpada saat trapperintah dievaluasi, bukan pada saat jebakan dipicu. Dalam hal ini, tidak ada bedanya, kecuali bahwa kode Anda rusak parah jika nilai tempdirberisi satu kutipan, sedangkan kode saya selalu berfungsi.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles Itu fitur yang bagus. Saya telah mencoba contoh kutipan tunggal Anda tanpa keberuntungan, jadi saya pikir trap tidak dapat mengevaluasi variabel saat runtime. Ternyata saya $tempdirdideklarasikan secara lokal dan harus didefinisikan secara global agar trap memiliki akses ke sana. Masuk akal sekarang ...
Enam
1
@Gilles ... selama $tempdir nilainya tidak berubah, yang pada dasarnya dapat diterima untuk semua tujuan. Berhati-hatilah untuk tidak menggunakan nama yang sama untuk membuat beberapa file temp / direktori ...
MestreLion
3

Alternatif yang lebih aman adalah menggunakan mktempuntuk membuat direktori dengan aman, lalu letakkan pipa bernama Anda di dalam direktori itu, lakukan rm -R $diruntuk menyingkirkannya pada akhirnya.

David Parks
sumber
Saya memilih untuk membuat FIFO dalam mktempdirektori, karena itu adalah satu-satunya jawaban yang dapat diterima, kalau-kalau Anda tidak memperhatikan, @Gilles sudah memposting jawaban ini secara mendalam.
JM Becker
2

Gunakan opsi "dry-run":

mkfifo $(mktemp -ut pipe.XXX)
polemon
sumber
1
Menurut halaman manual, penggunaan -uopsi "tidak dianjurkan".
dogbane
@dogbane Jadi penggunaannya -t, tapi selama itu bisa diandalkan, saya akan menggunakannya.
Polemon
maaf, di mana katanya -tberkecil hati?
dogbane
2
@dogbane Jika sangat penting, saya akan membuat aplikasi C kecil, memanggil mkstemp()fungsi ( linux.die.net/man/3/mkstemp ). The -tsaklar tidak berkecil hati, itu adalah -p, saya buruk.
polemon
1

Anda dapat menggunakan mktempuntuk membuat file sementara, lalu menghapusnya dan membuat pipa bernama dengan nama yang sama.

Sebagai contoh:

TMPPIPE=$(mktemp -t pipe.XXX) && {
    rm -f $TMPPIPE
    mkfifo $TMPPIPE
}
dogbane
sumber
Apakah menghapus $TMPPIPEsebelum mkfifomenghindari masalah 'tidak aman' terkait dengan melakukan TMPPIPE=`mktemp -u` ; mkfifo $TMPPIPE?
JM Becker
1
@ TechZilla mkfifosebenarnya aman, tidak seperti pembuatan file biasa dari shell. Jika tidak, membuat file kemudian menghapusnya tidak akan membantu sama sekali (sebenarnya itu akan sangat memudahkan pekerjaan penyerang dengan tidak mengharuskannya untuk menebak nama file). Jadi jawaban dogbane bekerja, tetapi pembuatan file perantara adalah komplikasi yang tidak berguna.
Gilles 'SO- stop being evil'
1
@Gilles, Tahukah Anda dalam hal apa mktemphalaman manual yang disebut -uopsi 'tidak aman'?
JM Becker
@dogbane, saya memberikan suara untuk jawaban Anda, dan komentar Anda yang saya rasa solid. Meskipun, saya sudah menyelesaikan ini kemarin .. Saya hanya menunggu untuk melihat ketika seseorang memposting solusi saya, atau semoga yang lebih baik. Jadi meskipun saya menggunakan mktemp -dAnda masih mendapat beberapa poin untuk input Anda. Terima kasih atas semua bantuan Anda, saya sangat menghargainya!
JM Becker
1
@ TechZilla mktemp -utidak aman saat membuat file biasa, karena memberikan perlindungan terhadap penolakan layanan (jika nama yang dihasilkannya cukup tidak dapat diprediksi) tetapi tidak mencegah penyerang membuat file di bawah hidung program. Membuat fifo alih-alih file biasa adalah kasus penggunaan yang jarang yang tidak ditangani oleh halaman manual.
Gilles 'SANGAT berhenti menjadi jahat'
0

Gunakan mkfifoatau mknoddi Unix, di mana dengan dua proses terpisah dapat mengakses pipa dengan nama - satu proses dapat membukanya sebagai pembaca, dan yang lainnya sebagai penulis.

mkfifo my_pipe
gzip -9 -c < my_pipe > out.gz
cat file > my_pipe

Pipa bernama dapat dihapus seperti file apa pun:

rm my_pipe

mkfifo --mode=0666 /tmp/namedPipe
gzip --stdout -d file.gz > /tmp/namedPipe

NamedPipe dapat digunakan file biasa untuk hanya membaca sekali.

http://www.linuxjournal.com/article/2156

Nikhil Mulley
sumber
2
Saya sepenuhnya sadar tentang pipa bernama, dan mkfifo. Itu tidak menjawab pertanyaan saya tentang pipa bernama sementara , lebih dari mkdiralamat membuat direktori sementara.
JM Becker
2
Bagaimana cara mengatasi masalah yang mktempditangani untuk membuat pipa bernama dengan aman ?
camh
1
oh ok, yang terbaik adalah membuat mereka di bawah / tmp, mereka adalah file sementara menurut definisi dan akan dihapus begitu sistem reboot. Atau lebih baik lagi, memiliki fungsi shell yang akan membuat namapipe dari mktemphasil itu sendiri (ofcourse dengan menghapus file temp terlebih dahulu dan kemudian berjalan mkfifopada yang sama). mktempjuga dapat digunakan untuk membuat direktori sementara, coba dengan -t -dswitch.
Nikhil Mulley