删除许多文件后出现“打开的文件太多”错误

Posted

技术标签:

【中文标题】删除许多文件后出现“打开的文件太多”错误【英文标题】:"too many open files" error after deleting many files 【发布时间】:2015-04-09 16:49:10 【问题描述】:

我的程序每 10 秒在指定目录中创建一个日志文件。然后在另一个线程中,它迭代该目录中的文件。如果文件有内容,则将其压缩并将其上传到外部存储,如果文件为空,则将其删除。程序运行一段时间后,我收到错误"too many open files" (gzopen failed, errno = 24)

当我查看/proc/<pid>/fd 内部时,我看到许多指向创建日志的同一目录中的文件的断开链接以及链接旁边的单词(deleted)

知道我做错了什么吗?我检查了两个线程中的返回值,close 函数(在写入日志的线程中)和boost::filesystem::remove(压缩和上传非空日志文件并删除空日志文件的线程)。所有的返回值都为零,而(deleted) 链接列表变得更长,每 10 秒购买 1 个。

我认为这个问题从未在 32 位上发生过,但最近我转向 64 位,现在我得到了这个惊喜。

【问题讨论】:

你关闭过文件吗? 我不仅关闭它们我还检查关闭函数的返回值,所有返回值都是零 你的testcase在哪里?来吧,你是一个长期的 SO 用户! 除非您发布更多代码,否则我们不知道如何为您提供帮助。 检查你的 ulimit -n 设置?您的新机器(64 位操作系统)的 ulimit 默认值可能与旧机器不同? 【参考方案1】:

您忽略了关闭您打开的文件。

根据您的描述,听起来您close 是您为登录日志线程而打开的文件,但您继续说您只是压缩和/或上传后的boost::filesystem::remove 文件。

记住:

您使用gzopen 打开的任何压缩文件都必须是gzclosed 您为压缩而打开的任何未压缩文件都必须关闭。 如果你打开一个文件来检查它是否为空,你必须关闭它。 如果您打开文件进行传输,则必须将其关闭。

/proc/pid/fd 的输出将非常有助于缩小范围,但不幸的是您没有发布它。看似无用的输出如何提供微妙提示的示例:

# You forgot to gzclose the output file after compressing it
l-wx------ user group 64 Apr 9 10:17 43 -> /tmp/file.gz (deleted)

# You forgot to close the input file after compressing it
lr-x------ user group 64 Apr 9 10:17 43 -> /tmp/file (deleted)

# You forgot to close the input file after logging
l-wx------ user group 64 Apr 9 10:17 43 -> /tmp/file (deleted)

# You forgot to close the input file after transferring it
lr-x------ user group 64 Apr 9 10:17 43 -> /tmp/file.gz (deleted)

【讨论】:

你是对的!你是个天才:) 当我检查文件大小时,我打开它以将 fd 传递给fstat,但从未关闭它。很明显您了解软件开发,非常感谢。 很高兴它有帮助。请记住,您可以简单地 stat 一个文件而不是 open+fstat+close 再一次,非常感谢你们明智的 cmets,我一定会在处理所有其他紧迫问题后进行调查 :)

以上是关于删除许多文件后出现“打开的文件太多”错误的主要内容,如果未能解决你的问题,请参考以下文章

延迟打开的文件导致“打开的文件太多”

Python 子进程:打开的文件太多

Tomcat中的错误“打开的文件太多”

OSError : [Errno 24] 打开的文件太多

Apache PHP/OSX Mavericks: - 无法打开流:打开的文件太多

多处理返回“打开的文件太多”,但使用 `with...as` 修复它。为啥?