Как безопасно очистить папку tmp в Linux

Как безопасно очистить папку tmp в Linux

Я использую 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

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