Чому (або як) кількість відкритих дескрипторів файлів, що використовуються коренем, перевищує ulimit -n?


13

Нещодавно у нашого сервера не вистачало дескрипторів файлів, і щодо цього у мене є деякі запитання. ulimit -nповинен дати мені максимальну кількість дескрипторів відкритого файлу. Це число 1024. Я перевірив кількість дескрипторів відкритого файлу, запустивши lsof -u root |wc -lі отримав 2500 фд. Це набагато більше 1024, тому я здогадався, що це означає, що число 1024 - це процес, а не кожен користувач, як я хоч. Ну, я побіг lsof -p$PidOfGlassfish|wc -lі отримав 1300. Це частина, яку я не отримую. Якщо ulimit -nце не максимальна кількість процесів на користувача або на один процес, то для чого це добре? Чи це не стосується кореневого користувача? І якщо так, то як я можу отримати повідомлення про помилку щодо закінчення дескриптора файлів?

EDIT: Єдиний спосіб, з якого я можу отримати сенс, 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), тому це здається кроком у правильному напрямку. "На жаль", у мене не виникає проблем із закінченням дескрипторів файлів, тому мені буде важко перевірити це.


2
lsof повідомляє про відображення пам'яті, а також про відкриті файли, тому ваш "wc" конвеєр дає надмірну оцінку кількості дескрипторів файлів, використовуваних у цьому процесі.
Річард Кеттвелл

ага! тепер це гарна інформація. Але я не зовсім впевнений, що розумію. Під «відображенням пам’яті» ви маєте на увазі файл, відображений у пам'яті? Це потребує обробки файлів, наскільки я розумію, або як ще ОС могла б оновити файл?
олігофрен

І наступне наступне: Який був би хороший спосіб знайти всі відкриті файли-ручки - ті, на які насправді впливають обмеження, накладені "ulimit -n"?
олігофрен

1
Для відображення пам'яті не потрібен відкритий файл. Якщо ви хочете лише перелічити відкриті файли, фільтрування виводу lsof - це, мабуть, найпростіший підхід.
Річард Кеттвелл

Дякую, відредагував мою відповідь. Використання ´lsof -u root | grep / | sort -k9 -u´, схоже, дає обґрунтовану відповідь. Це принаймні число менше, ніж ulimit -n.
олігофрен

Відповіді:


9

Я перевірив це у версії 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: Забагато відкритих файлів у журналах процесів)


Дякуємо, що перевірили це. Ви маєте ідею, чому lsof -p$PidOfGlassfish|wc -lмені дали 1300? Я здогадуюсь, що два підходи до підрахунку якось відрізняються. Якщо ні, то, можливо, обмеження не стосується кореневого користувача?
олігофрен

Просто цікаво, навіщо використовувати ls -lзамість ls? Останній має додатковий рядок (наприклад total 5), коли є 5 файлів. У такому випадку, використовуючи ls -l у наведеному вище прикладі, було б повідомлення 6, а не 5. Я використовую ls /proc/<pid>/fd | wc -l.
starfry

@starfry З мого боку це просто неохайність. Зазвичай я це роблю поетапно, і ls -lдає мені один запис на рядок, який потім перетворюю на щось інше. З курсів це також відбувається, коли трубопроводи нормальні ls(але не інакше).
олігофрен

3

Програма призначена для файлових ручок. Це стосується файлів, каталогів, розеток, трубних епох, eventfds, timerfds тощо тощо.

У будь-який момент під час запуску процесів обмеження можуть бути змінені. Відвідайте /proc/<pid>/limitsі перевірте, чи змінилися значення.


3

@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виключити дескриптори файлів типу: ВУХО / ERR / LTX / MEM / ММАП / PD / ТПС / TXT.

З сторінки lsof man:

   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-файлів пам'яті

JARfile, зібраний на пам'ять, у цьому випадку файл, який містить "класи JDK". Коли ви пам'ятаєте JAR-карту, ви можете дуже ефективно отримувати доступ до файлів, що знаходяться в ній (порівняно з читанням з початку). Sun JVM запам'ятовує карту пам'яті всіх JAR на класному шляху; якщо вашому коду програми потрібно отримати доступ до JAR, ви також можете зробити карту пам'яті.

Таким чином, такі речі, як tomcat / glassfish, також відображатимуть картографічні файли з пам'яттю. Я не перевіряв, чи відносяться вони до "ulimit -Sn"межі.

EDIT --- кінцевий фрагмент ---

Емпірично я виявив, що "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означають.


0

Здається, що ваші міркування є чимось на кшталт "я повинен знизити цю межу, щоб у мене не вичерпалися дорогоцінні дескриптори". Правда якраз зворотна - якщо у вашого сервера не вистачало дескрипторів файлів, вам потрібно підвищити цю межу з 1,024 до чогось більшого. Для реалістичної glassfishреалізації 32 768 є розумним.

Особисто я завжди підвищую межу приблизно до 8192 в цілому по системі - 1,024 - це просто смішно. Але ви захочете піднятися glassfishвище. Перевірити /etc/security/limits.conf. Ви можете додати спеціальний запис для користувача, який glassfishвиконує як.


Я не впевнений, як ти міг інтерпретувати мене так :-) Що мені було цікаво, чому це, мабуть, не застосовується. Я встановлю його вище, але хочу зрозуміти, як це працює. Якщо межа становить 1024, то як у Glassfish може бути 1300 ручок?
олігофрен

'lsof -u root | grep / | sort -k9 -u' друкує унікальні записи дескриптора файлу. Я здогадуюсь, що кількість рядків з цього числа є фактичним числом ulimit -n, яке стосується.
олігофрен

0

Ви хочете подивитися на загальносистемні обмеження, встановлені в / proc / sys / fs / file-max, і відрегулювати його там (до наступної перезавантаження) або встановити fs.file-max в sysctl.conf, щоб зробити його постійним. Це може стати в нагоді - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html


1
Цей коментар про баш не є точним. ulimit накладає набір обмежень для користувача-ідентифікатора для процесів, ініційованих через оболонку, що по суті є практично всім завдяки тому, як дерево процесів породжується в Unix, як операційні системи. Це не баш.
EightBitTony

Вибачте - відредагуйте, але коментар щодо загальносистемних обмежень все ще стоїть.
rnxrx

Це дуже малоймовірно, що він потрапляє в широкі межі системи. Можливо, але дуже малоймовірно.
Девід Шварц

EightBitTony: ulimit не встановлює ulimit для встановлення лімітів користувача-id. Його на кожен процес, коли застосовуються пам_ліміти. Промінь, що є "на кожного користувача", є "ulimit -u" "Максимальна кількість процесів, доступних для одного користувача"
Ні імені користувача,

0

Поширена помилка порівняння результату необмеженого дзвінка 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} / limit Якщо ви хочете перевірити, скільки файлів відкриває процес, отримайте його PID, а потім: ls -1 / proc / {PID} / fd | wc -l (зауважте, що це 'мінус один', а не конфігурувати з 'мінус ель')

Якщо ви хочете дізнатись деталі з lsof, але лише для тих файлових обробників, які рахуються за ліміт, спробуйте: thso: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt '-a

Зауваження: "файли" - це файли / з'єднання труби / tcp / тощо.

Зауважте, що іноді вам, мабуть, потрібно буде мати root або використовувати sudo, щоб отримати правильний результат для команд, без привілеїв іноді ви не маєте помилок, менше результатів.

і нарешті, якщо ви хочете знати, до яких файлів у вашій файловій системі здійснюється процес, перегляньте: lsof -p {PID} | греп / | awk '{print $ 9}' | сортувати | uniq

весело!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.