我最近发出了这个命令:
find . -type f | wc -l
计算我的 public_html 文件夹中有多少个文件。
不久之后,Nginx 返回了 500 内部服务器错误,error.log 中充斥着“打开文件过多”的错误。我想这也许是问题的根源?
答案1
使用 GNU find(Debian Squeeze 的 4.4.2)查看,strace -eopen find . -type f
答案似乎是“不,find 不会打开文件”,但它做打开目录:
open("details", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open(".uml", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
open("..", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
open(".dbus", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
等等。当然,所有这些命令都返回了相同的文件句柄 #,这强烈暗示 find 正在再次关闭它们。我创建了一组相当深的目录,似乎 find 用于..
向上移动目录,而不是保持目录打开。
但这确实看起来是一个非常了不起的巧合。
答案2
当然,文件就是目录,如果 find 在运行过程中没有关闭它们,理论上你在某些 Unixen 上仍然会面临一些微小的风险。运行完整的
strace find . -type f
并查看序列(来自linux):
openat(AT_FDCWD, "a", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 6
fchdir(6) = 0
getdents(6, /* 4 entries */, 32768) = 104
getdents(6, /* 0 entries */, 32768) = 0
close(6)
...