12

Я использую оперативную память для моих tmpfs /tmp, 2 ГБ, если быть точным. Обычно этого достаточно, но иногда процессы создают файлы там и не могут очистить после себя. Это может произойти, если они потерпят крах. Мне нужно удалить эти потерянные tmp файлы, иначе в будущем /tmp не хватит места.

Как я могу безопасно собрать мусор / TMP? Некоторые люди делают это, проверяя отметку времени последнего изменения, но этот подход небезопасен, поскольку могут существовать длительные процессы, которым все еще нужны эти файлы. Более безопасный подход - объединить условие отметки времени последней модификации с условием, что ни у одного процесса нет дескриптора файла для файла. Есть ли программа / скрипт / и т.д., которые воплощают этот подход или какой-то другой подход, который также безопасен?

Кстати, разрешает ли Linux/Unix режим открытия файла с созданием, при котором созданный файл удаляется при завершении процесса создания, даже если он произошел сбой?

7 ответов7

14

Вы можете попробовать что-то вроде этого:

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) для недоступных. Поскольку мы заинтересованы только в unaccessed те, мы ставим -not перед этим -exec
  • -exec echo {} ';' просто печатает все имена файлов, соответствующие критериям. Вы можете использовать -exec rm {} ';' вместо этого здесь, но так как это может удалить некоторые все еще используемые файлы, я думаю, что безопаснее сначала сделать простое эхо.
  • edit: вы можете захотеть добавить что-то вроде -name 'foo*.bar' или -uid 123 чтобы ограничить эффекты очистки конкретными шаблонами файлов или идентификаторами пользователей, чтобы избежать случайных эффектов.

К последнему пункту: Учтите, что могут быть файлы, которые записываются только один раз (например, при загрузке системы), но часто читаются (например, любой файл X-session-cookie). Поэтому я рекомендую добавить некоторые проверки имен, чтобы они влияли только на файлы, созданные неисправными программами.

edit2: К вашему последнему вопросу: файл не будет удален с диска, пока ни у какого процесса не будет открытого дескриптора к нему (по крайней мере, для родных файловых систем linux). Проблема заключается в том, что запись в каталоге удаляется немедленно, а это означает, что с момента удаления файла новые процессы больше не смогут его открыть (поскольку к нему не прикреплено имя файла).

Для получения дополнительной информации см .:https://stackoverflow.com/questions/3181641/how-can-i-delete-a-file-upon-its-close-in-c-on-linux

edit3: Но что, если я хотел бы автоматизировать весь процесс?

Как я уже сказал, могут быть файлы, которые записываются один раз, а затем читаются время от времени (например, файлы cookie сеанса X, файлы PID и т.д.). Они не будут исключены этим небольшим скриптом удаления (по этой причине вам может понадобиться выполнить тестовый прогон с echo прежде чем фактически удалять файлы).

Одним из способов реализации безопасного решения является использование atime .
atime хранит время последнего доступа к каждому файлу. Но эта опция файловой системы часто отключена, потому что она имеет некоторое влияние на производительность (согласно этому блогу где-то в 20-30% регионе). Есть относительное relatime , но оно записывает время доступа только в том случае, если mtime изменилось, так что этот нам не поможет.

Если вы хотите использовать atime , я бы порекомендовал иметь /tmp на отдельном разделе (в идеале, на виртуальном диске), чтобы влияние на производительность системы не было слишком большим.

После включения atime все, что вам нужно сделать, это заменить параметр -mtime в приведенной выше командной строке на -atime .
Вы можете удалить -not -exec fuser -s {} ';' , но я бы оставил его там просто для уверенности (в случае, если приложения сохраняют файлы открытыми в течение длительного периода времени).

Но имейте в виду, что нужно проверить команду с помощью echo прежде чем вы удалите все, что нужно вашей системе!

3

Не катай свои собственные.

У Debian/Ubuntu есть tmpreaper, он, вероятно, доступен и на других дисках.

# tmpreaper - cleans up files in directories based on their age

sudo apt-get install tmpreaper

cat /etc/tmpreaper.conf 
2

Что касается последней части вашего вопроса:

Хотя я не думаю, что существует режим открытия / создания «delete-this-if-I-die», процесс может безопасно удалить файл непосредственно после его создания, если он сохраняет дескриптор указанного файла открытым. Затем ядро сохранит файл на диске, и как только последний процесс, открывший файл, выйдет (будь то аварийно или нормально), пространство, занимаемое файлом, будет освобождено.

Для общего решения проблемы, заключающейся в том, что некоторые процессы иногда не очищают /tmp, я бы посоветовал взглянуть на пространства имен монтирования, описанные, например, здесь или здесь. Если рассматриваемый процесс является системным демоном, systemd и его нативная функция, позволяющая использовать частные /tmp файловые системы, могут представлять интерес.

0

Я согласен с вышесказанным, чтобы добавить к этому, хотя- я всегда запускаю lsof +L1 | grep tmp и либо убейте, либо перезапустите процессы, удерживающие "удаленные" файлы tmp: ПРИМЕР-

# lsof +L1 | grep tmp
xfce4-ter  1699  user   32u   REG    8,6      192     0 818552 /tmp/vte966VLX (deleted)
chrome     3301  user  138u   REG    8,6    16400     0 818547 /tmp/etilqs_Z0guKD7p6ork9iG (deleted)
0

для GUI попробуйте это; http://bleachbit.sourceforge.net/

очищает и скрабы. режим предварительного просмотра.

0

Вы можете просто сделать rm -rf /tmp/* и надеяться, что ничего не сломается ...

0

Получите список файлов старше, чем это так, исключите файлы, которые открыты чем-либо из этого списка:

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 \|: заменить новую строку на строку (ИЛИ в egrep)
egrep -v "foo|moo|bar": печатать строки, НЕ содержащие foo или moo или bar

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .