Назад | Перейти на главную страницу

«Находит» ли открытые файлы?

Недавно я выполнил эту команду: find . -type f | wc -l

Чтобы посчитать, сколько файлов в моей папке public_html.

Вскоре после этого Nginx вернул внутреннюю ошибку сервера 500, а журнал error.log был переполнен ошибкой «слишком много открытых файлов». Я подумал, может быть, это могло быть источником этой проблемы?

Смотря на strace -eopen find . -type f при использовании GNU find (4.4.2 из Debian Squeeze) ответ выглядит следующим образом: «Нет, 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 не закрывал их по ходу работы, теоретически вы все равно подвергались бы небольшому риску в некоторых 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)
...