Cara menghapus direktori secara otomatis ketika executable terbunuh

9

Cukup sering, kami menjalankan executable yang perlu menulis / membaca beberapa file sementara. Kami biasanya membuat direktori sementara, menjalankan executable di sana, dan menghapus direktori ketika skrip selesai.

Saya ingin menghapus direktori bahkan jika executable terbunuh. Saya mencoba membungkusnya:

#!/bin/bash
dir=$(mktemp -d /tmp/foo.XXXXXXX) && cd $dir && rm -rf $dir
/usr/local/bin/my_binary

Ketika my_binarymati, proses terakhir kernel akan menghapus direktori, karena skrip adalah proses terakhir yang menahannya inode; tapi saya tidak bisa membuat file apa pun di direktori yang dihapus.

#!/bin/bash
dir=$(mktemp -d /tmp/foo.XXXXXXX) && cd $dir && rm -rf $dir
touch file.txt

output touch: file.txt: No such file or directory

Yang terbaik yang bisa saya lakukan adalah menghapus direktori temp ketika proses mati, menangkap sinyal yang paling umum, dan menjalankan proses pembersihan dengan cron:

#!/bin/bash
dir=$(mktemp -d /tmp/d.XXXXXX) && cd "$dir" || exit 99
trap 'rm -rf "$dir"' EXIT
/usr/local/bin/my_binary

Apakah ada beberapa cara sederhana untuk membuat direktori yang benar-benar sementara yang akan dihapus secara otomatis ketika biner saat ini mati, tidak peduli apa?

Joaquin Cuenca Abela
sumber
1
berhati-hatilah karena Anda memiliki jendela kecil di mana cleanupdapat dieksekusi sebelum mktemp selesai. Anda mungkin ingin unset dirsebelum mengatur jebakan.
Stéphane Chazelas
tangkapan bagus, saya memperbarui skrip untuk menangani ini dan untuk menangani kegagalan di mktemp.
Joaquin Cuenca Abela
Saya pikir jalan keluar itu wajib. Tetap.
Joaquin Cuenca Abela
Contoh terakhir Anda menyebutkan cron, tetapi tidak ada hubungannya dengan cron. Contoh terakhir itu juga yang paling aman. Satu-satunya hal yang tidak akan ditangani adalah SIGKILL.
Patrick
Saya tidak memasukkan skrip cron yang saya jalankan untuk membuatnya tetap. Itu adalah menemukan pola yang cocok dengan dir lebih dari 1 jam dan rm mereka. Saya ingin tahu apakah ada solusi yang juga akan mencakup kasus sigkill, atau bahkan shutdown brutal di tengah naskah.
Joaquin Cuenca Abela

Jawaban:

3

Contoh terakhir Anda adalah brankas yang paling gagal.

trap 'rm -rf "$dir"' EXIT

Ini akan dieksekusi selama shell itu sendiri masih berfungsi. Pada dasarnya SIGKILL adalah satu-satunya hal yang tidak akan ditangani karena shell dihentikan secara paksa.
(mungkin SIGSEGV juga, tidak mencoba, tetapi dapat ditangkap)

Jika Anda tidak membiarkan shell membersihkannya sendiri, satu-satunya alternatif lain yang mungkin adalah meminta kernel melakukannya. Ini biasanya bukan fitur kernel, namun ada satu trik yang dapat Anda lakukan, tetapi memiliki masalah sendiri:

#!/bin/bash
mkdir /tmp/$$
mount -t tmpfs none /tmp/$$
cd /tmp/$$
umount -l /tmp/$$
rmdir /tmp/$$

do_stuff

Pada dasarnya Anda membuat tmpfs mount, dan kemudian malas melepasnya. Setelah skrip selesai akan dihapus.
Kelemahannya selain terlalu rumit, adalah bahwa jika skrip mati karena alasan apa pun sebelum unmount, Anda tidak akan mendapatkan tunggangan.
Ini juga menggunakan tmpfs, yang akan menghabiskan memori. Tetapi Anda bisa membuat proses lebih kompleks dan menggunakan sistem file loop, dan menghapus file yang mendukungnya setelah di-mount.


Pada akhirnya yang trapterbaik adalah kesederhanaan dan keamanan, dan kecuali Anda skrip mendapatkan SIGKILLed secara teratur, saya akan tetap menggunakannya.

Patrick
sumber
Apakah penting jika jebakan ditempatkan sebelum mktempatau sesudahnya? Saya akan berpikir jika jebakan ditempatkan tepat sebelum mktemp, maka bahkan jika sinyal keluar diterima setelah jebakan dan sebelum mktemp, semua yang akan terjadi adalah rm -rfperintah akan dijalankan dengan argumen kosong, tidak menghasilkan apa-apa. Tetapi jika jebakan itu setelah mktemp, mungkin ada jendela kecil peluang bahwa temp temp akan ditinggalkan. Atau apakah saya benar-benar tidak masuk akal?
Wildcard
1

Anda bisa menggunakan wait builtin untuk menunggu pekerjaan latar belakang selesai:

blah &
wait
rm -rf $DIR
Matthew Cline
sumber
Tapi itu setara dengan blah; rm -rf $DIR, kan? Ini memiliki masalah yang akan bocor $ DIR jika skrip terbunuh.
Joaquin Cuenca Abela
Jika skrip anak terbunuh, skrip induk masih akan ada untuk membersihkan setelah itu. Jika skrip induk juga terbunuh, maka ya, direktori akan tertinggal.
Matthew Cline