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

Почему (или как) количество открытых файловых дескрипторов, используемых пользователем 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), так что это кажется шагом в правильном направлении. «К сожалению» у меня нет проблем с исчерпанием файловых дескрипторов, поэтому мне будет сложно это проверить.

Я тестировал это в 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}' | сортировать | уникальный

радоваться, веселиться !