Как удалить каталог автоматически, когда исполняемый файл убит

9

Довольно часто мы запускаем исполняемый файл, который должен записывать / читать некоторые временные файлы. Обычно мы создаем временный каталог, запускаем там исполняемый файл и удаляем каталог, когда скрипт завершен.

Я хочу удалить каталог, даже если исполняемый файл убит. Я попытался обернуть это в:

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

Когда my_binaryумирает, последний процесс, в котором ядро ​​удалит каталог, так как скрипт является последним процессом, удерживающим это inode; но я не могу создать файл в удаленном каталоге.

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

выходы touch: file.txt: No such file or directory

Лучшее, что я могу придумать, это удалить временный каталог, когда процесс умирает, перехватывая наиболее распространенные сигналы, и запустить процесс очистки с помощью cron:

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

Есть ли какой-нибудь простой способ создать действительно временный каталог, который автоматически удаляется при смерти текущего двоичного файла, несмотря ни на что?

Хоакин Куэнка Абела
источник
1
имейте в виду, что у вас есть небольшое окно, которое cleanupможет быть выполнено до выполнения mktemp. Возможно, вы захотите, unset dirпрежде чем устанавливать ловушку.
Стефан Шазелас
хороший улов, я обновил скрипт, чтобы обработать это и обработать ошибку в mktemp.
Хоакин Куэнка Абела
Я думал, что выход был обязательным. Исправлена.
Хоакин Куэнка Абела
Ваш последний пример упоминает cron, но не имеет ничего общего с cron. Этот последний пример также наиболее надежен. Единственное, с чем он не справится, это SIGKILL.
Патрик
Я не включил скрипт cron, который я запускаю, чтобы он был лаконичным. По этой схеме можно найти совпадение с директорами старше 1 часа и найти их. Я хочу знать, есть ли какое-либо решение, которое также охватит случай сигкила или даже жестокое отключение в середине сценария.
Хоакин Куэнка Абела

Ответы:

3

Ваш последний пример - самый надежный.

trap 'rm -rf "$dir"' EXIT

Это будет выполняться до тех пор, пока сама оболочка все еще функционирует. По сути, SIGKILL - единственное, с чем он не справится, так как оболочка принудительно завершается.
(возможно, SIGSEGV тоже не пробовал, но его можно поймать)

Если вы не оставляете это на усмотрение оболочки, то единственная другая возможная альтернатива - заставить ядро ​​это делать. Обычно это не ядро, но есть один трюк, но у него есть свои проблемы:

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

do_stuff

По сути, вы создаете монтирование tmpfs, а затем ленивый размонтируете его. Как только скрипт будет выполнен, он будет удален.
Недостатком, кроме того, что он слишком сложен, является то, что если сценарий умирает по какой-либо причине перед размонтированием, у вас не будет монтирования.
Это также использует tmpfs, который будет использовать память. Но вы можете сделать процесс более сложным и использовать циклическую файловую систему, а также удалить файл, поддерживающий его после его монтирования.


В конечном счете, trapэто лучшее, что касается простоты и безопасности, и если ваш сценарий не получает SIGKILLed регулярно, я бы придерживался этого.

Патрик
источник
Имеет ли значение, если ловушка установлена ​​до mktempили после нее? Я бы подумал, что если ловушка будет помещена непосредственно перед mktemp, то даже если сигнал выхода был получен после ловушки и перед mktemp, все, что могло бы произойти, - это то, что rm -rfкоманда будет запущена с пустым аргументом, ничего не добившись. Но если бы ловушка была после mktemp, мог бы быть крошечный окошко шанса, что временный каталог останется. Или я совсем с базы?
Wildcard
1

Вы можете использовать ожидание встроенной команду ждать фонового задание до конца:

blah &
wait
rm -rf $DIR
Мэтью Клайн
источник
Но это будет эквивалентно blah; rm -rf $DIR, верно? Проблема в том, что он пропустит $ DIR, если скрипт будет убит.
Хоакин Куэнка Абела
Если дочерний сценарий будет уничтожен, родительский сценарий все еще будет очищать его. Если родительский скрипт также убит, то да, каталог останется позади.
Мэтью Клайн