
Я использую RAM для своего tmpfs /tmp, 2 ГБ, если быть точным. Обычно этого достаточно, но иногда процессы создают там файлы и не могут очистить их после себя. Это может произойти, если они аварийно завершатся. Мне нужно удалить эти потерянные файлы tmp, иначе будущий процесс исчерпает место в /tmp.
Как безопасно собрать мусор /tmp? Некоторые делают это, проверяя метку времени последнего изменения, но этот подход небезопасен, поскольку могут быть долго работающие процессы, которым все еще нужны эти файлы. Более безопасный подход — объединить условие метки времени последнего изменения с условием, что ни один процесс не имеет дескриптора файла для файла. Есть ли программа/скрипт/и т. д., которые воплощают этот подход или какой-то другой подход, который также безопасен?
Кстати, допускает ли Linux/Unix режим открытия файла с созданием, при котором созданный файл удаляется после завершения процесса создания, даже если это произошло из-за сбоя?
решение1
Возможно, вам захочется попробовать что-то вроде этого:
find /tmp -mtime +7 -and -not -exec fuser -s {} ';' -and -exec echo {} ';'
find используется для поиска файлов, соответствующих определенным критериям.
-mtime +7
выбирает только файлы старше 7 дней (можно использовать любое другое значение)-exec fuser -s {} ';'
вызывает fuser в тихом режиме для каждого файла, который соответствует критериям старости. fuser возвращает 0 (=true) для каждого файла, к которому был получен доступ прямо сейчас, и 1 (= false) для неиспользованных. Поскольку нас интересуют только неиспользованные, мы ставим-not
перед этим-exec
-exec echo {} ';'
просто выводит все имена файлов, соответствующие критериям. Возможно, вы захотите использовать-exec rm {} ';'
здесь вместо этого , но поскольку это может удалить некоторые все еще используемые файлы, я думаю, что безопаснее сначала сделать простое эхо.- редактировать:Возможно, вы захотите добавить что-то вроде
-name 'foo*.bar'
или-uid 123
ограничить эффекты очистки определенными шаблонами файлов или идентификаторами пользователей, чтобы избежать случайных эффектов.
По последнему пункту: учтите, что могут быть файлы, которые записываются только один раз (например, при загрузке системы), но часто считываются (например, любой X-session-cookie). Поэтому я рекомендую добавить некоторые проверки имен, чтобы влиять только на файлы, созданные вашими неисправными программами.
правка2: На ваш последний вопрос: Файл не будет удален с диска, пока ни один процесс не откроет дескриптор для него (по крайней мере, для собственных файловых систем Linux). Проблема в том, что запись каталога удаляется немедленно, что означает, что с момента удаления файла ни один новый процесс больше не сможет открыть файл (так как к нему не прикреплено имя файла).
Подробности смотрите здесь: https://stackoverflow.com/questions/3181641/how-can-i-delete-a-file-upon-its-close-in-c-on-linux
правка3:Но что, если я захочу автоматизировать весь процесс?
Как я уже сказал, могут быть файлы, которые записываются один раз, а затем время от времени считываются (например, куки-файлы сеанса X, файлы PID и т. д.). Они не будут исключены этим небольшим скриптом удаления (поэтому вам, возможно, захочется echo
сначала выполнить тестовый запуск, прежде чем удалять файлы).
Один из способов реализовать безопасное решение — использовать atime
.
atime
хранит время последнего доступа к каждому файлу. Но эта опция файловой системы часто отключается, поскольку она оказывает довольно сильное влияние на производительность (согласноэтот блоггде-то в районе 20-30%). Есть relatime
, но он записывает только время доступа, если mtime
оно изменилось, так что этот нам не поможет.
Если вы хотите использовать atime
, я бы рекомендовал иметь /tmp
отдельный раздел (в идеале RAM-диск), чтобы влияние на производительность всей системы не было слишком большим.
После atime
включения все, что вам нужно сделать, это заменить -mtime
параметр в приведенной выше командной строке на -atime
.
Вы можете удалить -not -exec fuser -s {} ';'
, но я бы оставил его там просто для уверенности (на случай, если приложения будут держать файлы открытыми в течение длительного периода времени).
Но не забудьте протестировать команду, echo
прежде чем удалять то, что все еще необходимо вашей системе!
решение2
Не скручивайте свои собственные.
В Debian/Ubuntu есть tmpreaper, вероятно, он доступен и в других дистрибутивах.
# tmpreaper - cleans up files in directories based on their age
sudo apt-get install tmpreaper
cat /etc/tmpreaper.conf
решение3
Относительно последней части вашего вопроса:
Хотя я не думаю, что существует режим открытия/создания «удалить это, если я умру», процесс может безопасно удалить файл сразу после его создания, пока он сохраняет дескриптор этого файла открытым. Затем ядро сохранит файл на диске, и как только последний процесс, открывший файл, завершит работу (будь то из-за сбоя или нормально), пространство, занимаемое файлом, будет освобождено.
Для общего решения проблемы, заключающейся в том, что некоторые процессы иногда не очищают /tmp, я бы посоветовал взглянуть на пространства имен монтирования, описанные, например, здесь:здесьилиздесь. Если рассматриваемый процесс является системным демоном,системди его встроенная функция, позволяющая использовать приватные файловые системы /tmp, может быть интересна.
решение4
Получить список файлов старше so и исключить файлы, открытые кем-либо из этого списка:
find /tmp -mtime +7 |\
egrep -v "`lsof -n +D /tmp | awk 'NR>1 {print $9}'| tr \\n \|`"
lsof -n +D /tmp
: поиск открытых файлов в /tmp
awk 'NR>1 {print $9}'
: печать только девятого столбца вывода lsof, исключая заголовки
tr \\n \|
: замена новой строки на bar (ИЛИ в egrep)
egrep -v "foo|moo|bar"
: печать строк, НЕ содержащих foo или moo или bar