Почему (или как) количество дескрипторов открытых файлов, используемых root, превышает ulimit -n?
Наш сервер недавно исчерпал файловые дескрипторы, и в связи с этим у меня есть несколько вопросов. ulimit -n
должен дать мне максимальное количество дескрипторов открытых файлов. Это число 1024. Я проверил количество дескрипторов открытых файлов, запустив lsof -u root |wc -l
и получил 2500 фдс. Это намного больше, чем 1024, поэтому я догадался, что это будет означать, что число 1024 для каждого процесса, а не для пользователя, как я. Ну я побежал lsof -p$PidOfGlassfish|wc -l
и получил 1300. Это часть, которую я не понимаю. Если ulimit -n
не является ли максимальное количество процессов на пользователя или на процесс, тогда для чего это нужно? Это не относится к пользователю root? И если да, то как я могу получить сообщения об ошибке исчерпания дескриптора файла?
РЕДАКТИРОВАТЬ: Единственный способ, которым я могу понять из ulimit -n
если применяется число открытых файлов (как указано в руководстве по bash), а не количество дескрипторов файлов (разные процессы могут открывать один и тот же файл). Если это так, то простого перечисления количества открытых файлов (с пометкой '/', исключая файлы с отображением в памяти) недостаточно:
lsof -u root |grep /|sort -k9 |wc -l #prints '1738'
Чтобы увидеть количество открытых файлов, мне нужно отфильтровать по столбцу имени только печать уникальных записей. Таким образом, следующее, вероятно, более правильно:
lsof -u root |grep /|sort -k9 -u |wc -l #prints '604'
Приведенная выше команда ожидает вывод в следующем формате из lsof:
java 32008 root mem REG 8,2 11942368 72721 /usr/lib64/locale/locale-archive
vmtoolsd 4764 root mem REG 8,2 18624 106432 /usr/lib64/open-vm-tools/plugins/vmsvc/libguestInfo.so
Это, по крайней мере, дает мне номер менее 1024 (число, сообщенное ulimit -n
), так что это похоже на шаг в правильном направлении. "К сожалению" я не испытываю никаких проблем с исчерпанием файловых дескрипторов, поэтому мне будет трудно это проверить.
6 ответов
Я проверял это в Linux версии 2.6.18-164.el5 - Red Hat 4.1.2-46. Я мог видеть, что ulimit применяется на процесс.
Параметр устанавливается на уровне пользователя, но применяется для каждого процесса.
Например: 1024 был предел. Было запущено несколько процессов, и файлы, открытые каждым из них, были подсчитаны с использованием
ls -l /proc/--$pid--/fd/ | wc -l
Не было ошибок, когда сумма файлов, открытых несколькими процессами, пересекла 1024. Я также проверил уникальное количество файлов, объединяющее результаты для разных процессов и подсчет уникальных файлов. Ошибки начали появляться только тогда, когда счетчик для каждого процесса превысил 1024. ( java.net.SocketException: слишком много открытых файлов в журналах процессов)
@oligofren
Я также провел некоторое тестирование, чтобы определить, как "ulimits -Sn"
за "open files"
был исполнен.
Как и плакат, выбранный в ссылке, ulimit для
"open files"
действительно применяется для каждого процесса. Чтобы увидеть текущие пределы процесса:cat /proc/__process_id__/limits
Чтобы определить, сколько файлов открыт у процесса, вам нужно использовать следующую команду:
lsof -P -M -l -n -d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt' -p __process_id__ -a | awk '{if (NR>1) print}' | wc -l
Объяснение вышеизложенного и мой метод / результаты тестирования
"-P -M -l -n"
Аргументы lsof просто нужны для того, чтобы lsof работал как можно быстрее. Не стесняйтесь вынимать их.
-P - inhibits the conversion of port numbers to port names for network files
-M - disable reporting of portmapper registrations for local TCP, UDP and UDPLITE ports
-l - inhibits the conversion of user ID numbers to login names
-n - inhibits the conversion of network numbers to host names for network files
"-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"
аргумент наставляет lsof
исключить файловые дескрипторы типа: cwd/err/ltx/mem/mmap/pd/rtd/txt.
Из справочной страницы lsof:
FD is the File Descriptor number of the file or:
cwd current working directory;
Lnn library references (AIX);
err FD information error (see NAME column);
jld jail directory (FreeBSD);
ltx shared library text (code and data);
Mxx hex memory-mapped type number xx.
m86 DOS Merge mapped file;
mem memory-mapped file;
mmap memory-mapped device;
pd parent directory;
rtd root directory;
tr kernel trace file (OpenBSD);
txt program text (code and data);
v86 VP/ix mapped file;
Я считал "Lnn,jld,m86,tr,v86"
как неприменимо к Linux и, следовательно, не удосужился добавить их в список исключений. Я не уверен насчет "Mxx"
,
Если ваше приложение использует отображенные в памяти файлы / устройства, вы можете удалить "^mem"
а также "^mmap"
из списка исключений.
РЕДАКТИРОВАТЬ --- начать отрывать ---
Изменить: я нашел следующую ссылку, которая указывает, что:
.so-файлы, отображаемые в память, технически не совпадают с дескриптором файла, который контролирует приложение. /proc//fd - точка измерения для дескрипторов открытых файлов
Так что, если ваш процесс использует файлы с отображением в памяти, вам нужно отфильтровать *.so файлы.
Кроме того, JVM от Sun будет хранить файлы JAR карты памяти.
Отображаемый в память JAR-файл, в данном случае файл, содержащий "классы JDK". Когда вы отображаете JAR в память, вы можете очень эффективно обращаться к файлам внутри него (вместо того, чтобы каждый раз читать его с самого начала). Sun JVM отобразит в памяти все файлы JAR на пути к классам; если вашему приложению необходим код для доступа к JAR, вы также можете отобразить его в памяти.
Таким образом, такие вещи, как tomcat/glassfish также будут отображать файлы jar, отображенные в памяти. Я не проверял, относятся ли они к "ulimit -Sn"
предел.
РЕДАКТИРОВАТЬ --- конец обрезки ---
Опытным путем я обнаружил, что "cwd,rtd,txt"
не учитываются в отношении лимита на файл процесса (ulimit -Sn).
Я не уверен "err,ltx,pd"
засчитываются в лимит файлов, поскольку я не знаю, как создавать файловые дескрипторы этих типов дескрипторов.
"-p __process_id__"
аргумент ограничивает lsof
возвращать информацию только для __process_id__
указано. Удалите это, если вы хотите получить счет для всех процессов.
"-a"
Аргумент используется для AND выбора (то есть аргументы "-p" и "-d").
"awk '{if (NR>1) print}'"
оператор используется для пропуска заголовка, который lsof
печатает на выходе.
Я тестировал, используя следующий Perl-скрипт:
File: test.pl
---snip---
#!/usr/bin/perl -w
foreach $i (1..1100) {
$FH="FH${i}";
open ($FH,'>',"/tmp/Test${i}.log") || die "$!";
print $FH "$i\n";
}
---snip---
Мне пришлось выполнить скрипт в отладчике perl, чтобы скрипт не завершал работу и не выпускал дескрипторы файлов.
Выполнить: perl -d test.pl
В отладчике Perl вы можете запустить программу, введя c
и нажав Enter, и если ваш ulimit -Sn
со значением 1024, вы обнаружите, что программа останавливается после создания Test1017.log
файл в /tmp
,
Если вы теперь идентифицируете pid процесса perl и используете выше lsof
Команда вы увидите, что он также выводит 1024.
Удалить "wc -l"
и заменить на "less"
чтобы увидеть список файлов, которые учитываются в пределе 1024. Удалить "-d ^....."
аргумент, а также видеть, что cwd,txt
а также rtd
дескрипторы не учитываются в пределе.
Если вы сейчас бежите "ls -l /proc/__process_id__/fd/ | wc -l"
, вы увидите возвращенное значение 1025. Это потому что ls
добавил "total 0"
заголовок к его выводу, который был посчитан.
Замечания:
Чтобы проверить, заканчивается ли в ОС дескрипторы файлов, лучше сравнить значение:
cat /proc/sys/fs/file-nr | awk '{print $1}'
с
cat /proc/sys/fs/file-max
https://www.kernel.org/doc/Documentation/sysctl/fs.txt документирует, что file-nr
а также file-max
имею в виду.
Ulimit для файловых дескрипторов. Это относится к файлам, каталогам, сокетам, каналам epolls, eventfds, timerfds и т. Д. И т. Д.
В любой момент при запуске процессов ограничения могли быть изменены. Визит /proc/<pid>/limits
и посмотреть, если значения были изменены.
Вы хотите взглянуть на системные ограничения, установленные в / proc / sys / fs / file-max, и отрегулировать их там (до следующей перезагрузки) или установить fs.file-max в sysctl.conf, чтобы сделать его постоянным. Это может быть полезно - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html
Похоже, ваши рассуждения звучат примерно так: "Мне нужно снизить этот предел, чтобы у меня не заканчивались драгоценные дескрипторы". На самом деле все наоборот: если на вашем сервере заканчиваются файловые дескрипторы, вам нужно увеличить этот предел с 1024 до чего-то большего. Для реалистичного glassfish
реализация, 32,768 является разумным.
Лично я всегда поднимаю лимит примерно до 8 192 по всей системе - 1024 просто смешно. Но вы хотите поднять glassfish
выше. Проверьте /etc/security/limits.conf
, Вы можете добавить специальную запись для пользователя glassfish
работает как.
Распространенная ошибка - сравнивать результат необработанного вызова lsof с предполагаемым лимитом.
Для глобального ограничения (/proc/sys/fs/file-max) вы должны взглянуть на /proc/sys/fs/file-nr -> значение fist указывает, что используется, а последнее значение - ограничение
Ограничение OpenFile для каждого процесса, но может быть определено для пользователя, см. Команду "ulimit -Hn" для ограничений пользователя и см. /Etc/security/limits.conf для определений. Обычно применяется с "пользователем приложения", например:"tomcat": установите ограничение в 65000 для пользователя tomcat, который будет применяться к процессу Java, который он запускает.
Если вы хотите проверить лимит, примененный к процессу, получите его PID, а затем: cat /proc/${PID}/limit. Если вы хотите проверить, сколько файлов открывается процессом, получите его PID, а затем: ls -1 /proc/{PID}/fd | wc -l (обратите внимание, для ls это "минус один", не путать с "минус эль")
Если вы хотите узнать подробности с помощью lsof, но только для тех обработчиков файлов, которые учитывают лимит, попробуйте выполнить следующее: lsof -p ${PID} | grep -P "^(\w+\s+){3}\d+\D+" lsof -p ${PID} -d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt' -a
Примечание: "файлы" - это файлы / pipe / TCP-соединения / и т. Д.
Обратите внимание, что иногда вам, вероятно, понадобится быть пользователем root или использовать sudo для получения правильного результата для команд, без привилегий иногда у вас не будет ошибок, только меньше результатов.
и, наконец, если вы хотите узнать, к каким "файлам" в вашей файловой системе обращается процесс, взгляните на: lsof -p {PID} | grep / | awk '{print $9}' | сортировать | уник
повеселись!