Можно ли очистить временные файлы перед их использованием в оболочке?

Можно ли очистить временные файлы перед их использованием в оболочке?

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

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

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

В оболочке я часто вижу что-то похожее на:

generate-the-file -o the-file
[...loads of other stuff that may use stdout or not...]
do_slow_processing < the-file
rm the-file

Но если программа выйдет из строя раньше, rmпользователю придется ее очистить the-file.

В Perl вы можете сделать:

open(my $filehandle, "<", "the-file") || die;
unlink("the-file");
while(<$filehandle>) {
  # Do slow processing stuff here
  print;
}
close $filehandle;

Затем файл удаляется сразу после открытия.

Есть ли подобная конструкция в shell?

решение1

Это протестировано в csh, tcsh, sh, ksh, zsh, bash, ash, sash:

echo foo > the-file
(rm the-file; cat) < the-file | do_slow_processing
do_other_stuff

или, если вы предпочитаете:

(rm the-file; do_slow_processing) < the-file
do_other_stuff

Интересно, что это также работает для fifos:

mkfifo the-fifo
(rm the-fifo; cat) < the-fifo | do_slow_processing &
echo foo > the-fifo

Это происходит потому, что читатель заблокирован до тех пор, пока что-то не будет написано.

решение2

generate-the-file > the-file
exec 5< the-file
rm the-file
...
do_slow_processing 0<&5

Примечания:

  • Вам нужно запустить exec без исполняемого файла, так как это повлияет на дескрипторы самой оболочки.
  • Доступно только до 9 fd
  • Вы можете использовать /proc/self/fd/X, если вам нужно имя файла. Этот интерфейс непереносим между разновидностями UNIX (хотя, возможно, он работает для вас).
  • Попытка снова прочитать fd (например, два вызова cat 0<&5) не удастся, так как вы находитесь в EOF. Вам нужно будет перемотать его назад или преодолеть его, прочитав через/proc/self/fd/X
  • В большинстве случаев, как описано выше, вы можете обойтись без фактического файла, а сделать простоеgenerate-the-file | do_slow_processing

Обновлять:

OP упоминает, что generate-the-fileможет не выводить свой вывод в stdout. Для этого есть несколько идиом:

  • Укажите выходной файл -. Обычно принимают выходной файл - для обозначения stdout. Этоподтверждено POSIX.1-2017:

    Правило 13: Для утилит, использующих операнды для представления файлов, которые необходимо открыть для чтения или записи, операнд «-» следует использовать только для обозначения стандартного ввода (или стандартного вывода, если из контекста ясно, что указывается выходной файл) или файла с именем «-».

(для утилит, отличных от тех, где это явно определено, это определяется реализацией, но есть большая вероятность, что это поддерживается вашим generate-the-fileинструментом)

Это не будет работать на всех оболочках и требует поддержки ОС для имен файлов fd.

решение3

В bashоболочке очистку можно выполнить с помощью trapвстроенной команды EXIT (в bashоболочке введите help trap):

trap 'rm temp-file' EXIT

Эта функция также существует в dashоболочке, часто именуемой как . shв современных дистрибутивах Linux.

Связанный контент