mktemp
Безопасное создание временных файлов и каталогов с уникальными именами
mktemp создаёт временный файл (или с -d — каталог) с непредсказуемым уникальным именем и печатает путь к нему. Файл создаётся с правами 600, каталог — 700: доступ только у владельца. Путь сохраняют в переменную, а удаление поручают trap. В песочнице — GNU coreutils 9.4.
Синтаксис
mktemp [опции] [шаблон]
Без шаблона: $TMPDIR/tmp.XXXXXXXXXX (если TMPDIR не задан — /tmp). Каждая X в конце шаблона заменяется случайной буквой или цифрой; их должно быть не меньше трёх.
Опции
| Опция | Что делает |
|---|---|
-d | создать каталог, а не файл |
-p каталог | создать в этом каталоге; шаблон — просто имя. -p "" или -p без значения — $TMPDIR, иначе /tmp |
--tmpdir[=каталог] | длинная форма -p |
-t | шаблон — только имя; каталог — $TMPDIR, если задан (он важнее -p!), иначе из -p, иначе /tmp. Устаревшая форма, вместо неё --tmpdir |
--suffix=.ext | добавить суффикс после X: tmp.Ab3dE.conf |
-u | ничего не создавать, только напечатать имя (небезопасно: имя может успеть занять кто-то другой) |
-q | не печатать ошибку, если создать не удалось (код возврата всё равно 1) |
Куда попадёт файл
| Вызов | Где создаётся |
|---|---|
mktemp | $TMPDIR или /tmp |
mktemp app.XXXXXX | в текущем каталоге: шаблон с относительным путём |
mktemp /var/tmp/app.XXXXXX | точно по пути из шаблона |
mktemp -p /var/tmp | /var/tmp/tmp.XXXXXXXXXX — -p важнее TMPDIR |
mktemp -t app.XXXX | $TMPDIR/app.XXXX или /tmp/app.XXXX |
mktemp --tmpdir app.XXXXXX.json | $TMPDIR или /tmp, суффикс после X тоже допустим |
Уборка через trap
#!/bin/bash
set -euo pipefail
tmp=$(mktemp -d)
trap 'rm -rf -- "$tmp"' EXIT # сработает при любом выходе
curl -fsSL https://example.com/data.json -o "$tmp/data.json"
jq '.items' "$tmp/data.json"
EXIT-ловушка в bash срабатывает при обычном завершении, при выходе по set -e и при завершении по SIGTERM/SIGINT. Не сработает только при SIGKILL (kill -9) — тут не поможет ничто.
Примеры
# временный файл
tmp=$(mktemp)
sort data.txt > "$tmp" && mv "$tmp" data.txt
# временный каталог
work=$(mktemp -d)
# понятный префикс — легче найти в /tmp, если что-то осталось
mktemp -t backup.XXXXXX
# с расширением — некоторые программы смотрят на него
mktemp --suffix=.json
# рядом с целевым файлом (та же ФС) — для атомарной замены через mv
tmp=$(mktemp -p /etc/myapp app.conf.XXXXXX)
# проверить, что создание удалось
tmp=$(mktemp) || { echo 'не удалось создать временный файл' >&2; exit 1; }
Подводные камни
- Не придумывай имена сам.
/tmp/myscript.$$предсказуем: другой пользователь может заранее создать ссылку с таким именем, и скрипт запишет данные туда, куда она ведёт.mktempсоздаёт файл атомарно и с правами600. - Мало
X:mktemp app.XX— «too few X's in template». Нужно минимум три, лучше шесть и больше. - Шаблон без пути создаётся в текущем каталоге, а не в
/tmp. Хочешь в/tmp—-t,-pили полный путь. - Права
600. Если временный файл потом станет постоянным (черезmv), у него останутся права600— поменяй ихchmod. - Без
trapмусор копится: скрипт упал посередине — файл остался в/tmp. Ставьtrapсразу послеmktemp. - Одинарные кавычки в
trap. Вtrap 'rm -rf -- "$tmp"' EXITпеременная раскроется при срабатывании. С двойными кавычками она подставится сразу — работает, но ломается, если в пути есть пробелы или кавычки.