如何在Linux上安全地清理tmp文件夹


12

我使用RAM作为我的tmpfs / tmp,2GB,确切地说。通常情况下,这已足够,但有时,进程会在其中创建文件,并且无法自行清理。如果它们崩溃就会发生这种情况我需要删除这些孤立的tmp文件,否则将来的进程将耗尽/ tmp上的空间。

我怎样才能安全地收集垃圾/ tmp?有些人通过检查上次修改时间戳来做到这一点,但这种方法是不安全的,因为可能有长时间运行的进程仍然需要这些文件。更安全的方法是将最后修改时间戳条件与没有进程具有文件的文件句柄的条件组合。是否有一个程序/脚本/等体现了这种方法或其他方法也是安全的?

顺便提一下,Linux / Unix是否允许创建文件的模式,其中创建过程终止时删除创建的文件,即使它是从崩溃中删除的?


检查是否可以使用tmpfs而不是/ tmp: kernel.org/doc/Documentation/filesystems/tmpfs.txt
ott--

Answers:


14

你可能想尝试这样的事情:

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

find用于查找符合特定条件的文件。

  • -mtime +7 仅选择超过7天的文件(您可以使用任何其他值)
  • -exec fuser -s {} ';' 对于与旧标准匹配的每个文件,以静默方式调用fuser。对于未访问的每个文件,fuser返回0(= true),对于未访问的文件,fuser返回1(= false)。因为我们只对未被接受的人感兴趣,所以我们放了一个 -not 在这之前 -exec
  • -exec echo {} ';' 只打印符合条件的所有文件名。你可能想要使用 -exec rm {} ';' 而在这里,但由于这可能会删除一些仍在使用的文件,我认为首先做一个简单的回声更安全。
  • 编辑: 你可能想要添加类似的东西 -name 'foo*.bar' 要么 -uid 123 限制清理对特定文件模式或用户ID的影响,以避免意外影响。

最后一点:考虑可能只有一次写入文件(例如在系统启动时)但经常读取(例如任何X-session-cookie)。因此,我建议添加一些名称检查,以仅影响由错误程序创建的文件。

EDIT2: 对于你的上一个问题:在没有进程打开句柄之前,文件不会从磁盘中删除(至少对于本机linux文件系统)。问题是目录条目被立即删除,这意味着从删除文件开始,没有新进程可以再打开文件(因为没有附加文件名)。

详情见: https://stackoverflow.com/questions/3181641/how-can-i-delete-a-file-upon-its-close-in-c-on-linux

EDIT3: 但是,如果我想自动完成整个过程呢?

正如我所说,可能存在一次写入然后每隔一段时间读取一次的文件(例如X会话cookie,PID文件等)。这些小删除脚本不会排除这些(这就是为什么你可能想要进行测试运行的原因 echo 首先在实际删除文件之前)。

实现安全解决方案的一种方法是使用 atime
atime 存储上次访问每个文件的时间。但是该文件系统选项通常被禁用,因为它对性能有很大的影响(根据 这个博客 在20-30%地区的某个地方)。有 relatime,但是那个只写了访问时间 mtime 已经改变了,所以这个不会帮助我们。

如果你想使用 atime,我建议有 /tmp 在一个单独的分区(理想情况下是一个ramdisk),以便对整个系统的性能影响不是太大。

一旦 atime 已启用,您所要做的就是更换 -mtime 上面命令行中的参数 -atime
你也许可以删除 -not -exec fuser -s {} ';',但我保留它只是为了确保(如果应用程序保持文件打开很长一段时间)。

但请记住使用测试命令 echo 在你最终删除你的系统仍然需要的东西之前!


不错。如果文件在没有更新的情况下被长时间运行的进程关闭呢?如果它们是上下文文件,你可能会松开进程上下文(诚然,这不是一个非常聪明的过程;但是需要知道'横向'的预期副作用 /tmp/ 清理) 。
nik

这就是这种方法的问题(正如我在最后一段中指出的那样)。这里最好的方法是添加uid / gid或文件模式检查(相应地编辑答案)
mreithub

这应该放在一个cron脚本......?
CMCDragonkai

@CMCDragonkai当然你可以把它放到crontab中。但正如我所提到的那样,可能存在被访问但未写入的文件,因此可能不会被这个小脚本过滤掉。这就是为什么首先打印受影响文件列表然后决定是否删除它们更安全的原因。如果你的 /tmp 在一个单独的分区(例如ramdisk)上,您可以启用 atime 为它而使用 -atime 的参数 find
mreithub

我打算在服务器上这样做。因此我无法在那里统计tmp中的所有文件。会有任何问题吗?另外我以为我们本来打算使用relatime而不是atime?
CMCDragonkai

3

不要自己动手。

Debian / Ubuntu有tmpreaper,它也可能在其他dists中可用。

# 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

2

关于你问题的最后部分:

虽然我不认为存在“删除 - 如果我死”的打开/创建模式,但只要它保持打开所述文件的句柄,进程就可以在创建文件后直接安全地删除文件。然后内核将文件保存在磁盘上,一旦打开文件的最后一个进程退出(通过崩溃或正常),文件占用的空间将被释放。

对于某些进程有时不清理/ tmp的问题的一般方法,我建议看一下mount命名空间,例如描述 这里 要么 这里 。如果有问题的进程是系统守护进程, systemd 并且它的原生功能允许私有/ 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输出的第9列,不包括标题
tr \\n \|:用bar替换换行符(在egrep中为OR)
egrep -v "foo|moo|bar":打印行不包含foo或moo或bar


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)

2
SU随机安排帖子 - 所以没有上方或下方。你指的是哪个帖子?
Journeyman Geek

0

你可以做到 rm -rf /tmp/* 希望没有什么打破......


建议做一些事情“并希望没有什么打破”并没有真正回答OP的“是否有一个 安全的方式 去做这个。也许您可以详细说明为什么您的建议是安全的?
bertieb

@bertieb好点。我想如果不以root身份运行它可能是安全的,但是...
Solomon Ucko
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.