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

30644
Syncopated

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

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

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

12
Проверьте, можете ли вы использовать tmpfs вместо / tmp: http://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt ott-- 11 лет назад 0

7 ответов на вопрос

14
mreithub

You might want to try something like that:

find /tmp -mtime +7 -and -not -exec fuser -s {} ';' -and -exec echo {} ';'

find is used to find files that match certain criteria.

  • -mtime +7 only selects files that are older than 7 days (you may use any other value)
  • -exec fuser -s {} ';' calls fuser in silent mode for every file that matches the oldness criteria. fuser returns 0 (=true) for every file that's been accessed right now and 1 (= false) for the unaccessed ones. As we are only interested in the unaccessed ones, we put a -not in front of this -exec
  • -exec echo {} ';' just prints all file names matching the criteria. you might want use -exec rm {} ';' instead here, but as this may delete some still-in-use files, I think it's safer to do a simple echo first.
  • edit: You might want to add something like -name 'foo*.bar' or -uid 123 to limit the effects of the cleanup to specific file patterns or user IDs to avoid accidental effects.

To the last point: Consider that there might be files that are only written once (e.g. at system boot) but read frequently (e.g. any X-session-cookie). Therefore I recommend adding some name checks to only affect files created by your faulty programs.

edit2: To your last question: A file won't get deleted from disk until no process has an open handle to it (at least for native linux filesystems). The problem is that the directory entry is removed immediately which means that from the time you remove the file no new processes can open the file anymore (as there's no filename attached to it).

For details see: https://stackoverflow.com/questions/3181641/how-can-i-delete-a-file-upon-its-close-in-c-on-linux

edit3: But what if I wanted to automate the whole process?

As I said, there might be files that are written once and then read every once in a while (e.g. X session cookies, PID files, etc.). Those won't be excluded by this little removal script (which is the reason why you might wanna do a test run with echo first before actually deleting files).

One way to implement a safe solution is to use atime.
atime stores the time each file was last accessed. But that file system option often is disabled because it has quite some performance impact (according to this blog somewhere in the 20-30% region). There's relatime, but that one only writes the access time if mtime has changed, so this one won't help us.

If you want to use atime, I'd recommend to have /tmp on a separate partition (ideally a ramdisk) so that the performance impact on the whole system isn't too big.

Once atime is enabled, all you have to do is to replace the -mtime parameter in the above command line with -atime.
You might be able to remove the -not -exec fuser -s {} ';', but I'd keep it there just to be sure (in case applications keep files open for a long period of time).

But keep in mind to test the command using echo before you end up removing stuff your system still needs!

отлично. Как насчет файлов, закрытых длительным процессом, пока он не обновляет их? Если они являются файлами контекста, вы можете потерять контекст процесса (по общему признанию, это не очень умный процесс, но нужно знать ожидаемые побочные эффекты «боковой» очистки / tmp / `). nik 11 лет назад 0
В этом проблема этого подхода (как я указывал в последнем абзаце). Наилучший подход здесь - это добавить uid / gid или проверки шаблонов файлов (соответственно отредактировал ответ) mreithub 11 лет назад 0
Должно ли это быть помещено в скрипт cron ...? CMCDragonkai 9 лет назад 0
@CMCDragonkai Конечно, вы можете поместить это в crontab. Но, как я уже упоминал, могут быть файлы, к которым обращаются, но которые не записываются, и поэтому могут не фильтроваться этим небольшим скриптом. Вот почему безопаснее сначала распечатать список затронутых файлов, а затем решить, удалять их или нет. Если ваш `/ tmp` находится в отдельном разделе (например, на виртуальном диске), вы можете включить для него` atime` и использовать параметр `-atime` в` find`. mreithub 9 лет назад 0
Я планирую сделать это на сервере. Поэтому я не могу быть там, чтобы считать все файлы в TMP все время. Будут ли какие-либо проблемы? Кроме того, я думал, что мы должны были использовать relaytime, а не atime? CMCDragonkai 9 лет назад 0
@CMCDragonkai Я не могу сказать, что я эксперт в "atime". Это был просто намек на другое возможное решение вашей проблемы. mreithub 9 лет назад 0
@CMCDragonkai `relaytime` в нашем случае не работает, так как обновляет atime только один раз после каждого изменения файла. Я обновил ответ, чтобы дать вам немного больше информации. mreithub 9 лет назад 0
Я полагаю, что atime не является большой проблемой, если вы используете tmpfs или ramfs. Я использую tmpfs конечно. Хотя я хотел бы, чтобы были некоторые ориентиры, показывающие компромиссы. CMCDragonkai 9 лет назад 0
Когда вы завершаете работу с файлами внутри tmpfs / ramfs, означает ли это, что файл существует на диске? CMCDragonkai 9 лет назад 0
@CMCDragonkai Нет, эти файловые системы предназначены только для оперативной памяти. Как только он отключен, все данные будут потеряны mreithub 9 лет назад 0
Правильно, и он отключается во время выключения! CMCDragonkai 9 лет назад 0
3
Gringo Suave

Don't roll your own.

Debian/Ubuntu have tmpreaper, it's probably available in other dists as well.

# tmpreaper - cleans up files in directories based on their age sudo apt-get install tmpreaper cat /etc/tmpreaper.conf 
В файле `/ etc / tmpreaper.conf`, если я установил как` / tmp`, так и `/ var / tmp` в качестве каталогов очистки, вы можете долго рекомендовать параметр` TMPREAPER_TIME` или максимальное значение назад tmp файлы для удаления? Я слышал, что для файлов `/ var / tmp` лучше сохранять возраст, чем для файлов` / tmp`. Но если они могут быть установлены только с одинаковым максимальным возрастом, я понятия не имею. Xiaodong Qi 7 лет назад 0
2
Claudius

Regarding the last part of your question:

While I don’t think that an ‘delete-this-if-I-die’ open/creation mode exists, a process can safely delete a file directly after creating it, as long as it keeps a handle to said file open. The kernel will then keep the file on disk and as soon as the last process who had opened the file exits (be it by crash or normally), the space occupied by the file will be freed.

For a general way around the problem that some processes sometimes don’t clean up /tmp, I would suggest having a look at mount namespaces, described, for example here or here. If the process in question is a system daemon, systemd and its native feature to allow private /tmp filesystems might be of interest.

0
wuxmedia

for a GUI try this; http://bleachbit.sourceforge.net/

cleans and scrubs. preview mode.

0
Ярослав Рахматуллин

Obtain a list of files older than so an so, exclude files that are open by anything from that list:

find /tmp -mtime +7 |\ egrep -v "`lsof -n +D /tmp | awk 'NR>1 '| tr \\n \|`" 

lsof -n +D /tmp: look for open files in /tmp
awk 'NR>1 ': print only the ninth column of lsof output, excluding the headers
tr \\n \|: replace new-line by bar (OR in egrep)
egrep -v "foo|moo|bar": print lines NOT containing foo or moo or bar

0
SeaPhor

Я согласен с вышесказанным, чтобы добавить к нему, хотя - я всегда запускаю 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) 
SU случайным образом расставляет посты - так что нет ни выше, ни ниже. На какой пост вы ссылаетесь? Journeyman Geek 9 лет назад 2
0
Solomon Ucko

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

Предложение сделать что-то «и надеяться, что ничего не сломается» на самом деле не отвечает ОП «если есть ** безопасный способ ** сделать это. Возможно, вы могли бы уточнить, почему ваше предложение безопасно? bertieb 5 лет назад 0
@bertieb Хороший вопрос. Я думаю, это, вероятно, безопасно, если он не запускается от имени root, но ... Solomon Ucko 5 лет назад 0

Похожие вопросы