На нашем сервере недавно закончились файловые дескрипторы, и по этому поводу у меня есть несколько вопросов. 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
), так что это кажется шагом в правильном направлении. «К сожалению» у меня нет проблем с исчерпанием файловых дескрипторов, поэтому мне будет сложно это проверить.
Я тестировал это в 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"
было принудительно.
Как плакат Выбранный упомянутый в ссылка на сайт, предел для "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"
аргумент используется для И выбор (т.е. аргументы "-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
и посмотрите, были ли изменены значения.
Похоже, что вы рассуждаете примерно так: «Я должен снизить этот предел, чтобы у меня не закончились драгоценные дескрипторы». На самом деле все обстоит с точностью до наоборот - если на вашем сервере закончились файловые дескрипторы, вам необходимо поднять этот предел от 1024 до чего-то большего. Для реалистичного glassfish
реализация, 32 768 является разумным.
Лично я всегда увеличиваю лимит до 8192 для всей системы - 1024 - это просто смешно. Но ты хочешь поднять glassfish
выше. Проверьте /etc/security/limits.conf
. Вы можете добавить специальную запись для пользователя glassfish
работает как.
Вы хотите взглянуть на общесистемные ограничения, установленные в / proc / sys / fs / file-max, и настроить их там (до следующей перезагрузки) или установить fs.file-max в sysctl.conf, чтобы сделать его постоянным. Это может быть полезно - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html
Распространенная ошибка при сравнении результата необработанного вызова lsof с предполагаемым лимитом.
Для глобального ограничения (/ proc / sys / fs / file-max) вам следует взглянуть на / proc / sys / fs / file-nr -> первое значение указывает, что используется, а последнее значение - это предел
Ограничение OpenFile существует для каждого процесса, но может быть определено для пользователя, см. Команду "ulimit -Hn" для пользовательских ограничений и см. /Etc/security/limits.conf для определения. Обычно применяется с «пользователем приложения», например: «tomcat»: установите ограничение на 65000 для пользователя tomcat, которое будет применяться к запускаемому им java-процессу.
Если вы хотите проверить ограничение, примененное к процессу, получите его PID, а затем: cat / proc / $ {PID} / limits. Если вы хотите проверить, сколько файлов открыто процессом, получите его PID, а затем: ls -1 / proc / {PID} / fd | wc -l (обратите внимание, что для ls это 'минус один', не путать с 'минус el')
Если вы хотите узнать подробности с помощью lsof, но только для тех обработчиков файлов, которые учитываются в лимите, попробуйте с помощью thoses: 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 connections / и т. Д.
Обратите внимание, что иногда вам, вероятно, потребуется быть root или использовать sudo для получения правильного результата для команд, без привилегий иногда у вас нет ошибки, просто меньше результатов.
и, наконец, если вы хотите знать, к каким «файлам» в вашей файловой системе обращается процесс, посмотрите: lsof -p {PID} | grep / | awk '{print $ 9}' | сортировать | уникальный
радоваться, веселиться !