На комп’ютерах із Linux системні ресурси розподіляються серед користувачів. Якщо ви використовуєте більше ресурсів, ніж вам належить, то ви досягнете верхньої межі. Тим самим Ви ускладните роботу інших користувачів або процесів.
Загальні системні ресурси
Серед інших своїх численних завдань ядро комп’ютера з Linux завжди зайняте спостереженням за тим, хто скільки використовує кінцевих системних ресурсів, таких як ОЗУ та цикли ЦП. Розрахована на багато користувачів система вимагає постійної уваги, щоб переконатися, що люди та процеси не використовують будь-який конкретний системний ресурс більше, ніж це необхідно.
Наприклад, несправедливо, якщо хтось використовує стільки процесорного часу, що комп’ютер здається повільним для решти. Навіть якщо ви єдина людина, яка використовує ваш комп’ютер з Linux, є обмеження, встановлені для ресурсів, які можуть використовувати ваші процеси. Зрештою, ви все ще просто ще один користувач.
Деякі системні ресурси добре відомі та очевидні, наприклад, ОЗУ, цикли процесора та місце на жорсткому диску. Але існує набагато більше ресурсів, які відстежуються і для яких у кожного користувача або кожного процесу, що належить користувачеві, є встановлена верхня межа. Одним із них є кількість файлів, які процес може відкрити одночасно.
Якщо ви коли-небудь бачили повідомлення про помилку «Відкрито занадто багато файлів» у вікні терміналу або знаходили його у системних журналах, це означає, що досягнуто верхньої межі, і процесу більше не дозволено відкривати файли.
Це не просто файли, які ви відкривали
Існує загальносистемне обмеження кількості відкритих файлів, які може обробляти Linux. Як ми побачимо, це дуже велике число, але є межа. У кожного процесу користувача є виділене, яке вони можуть використовувати. Кожен із них отримує невелику частку загальної суми системи, виділеної ним.
Що насправді виділяється, то це кількість дескрипторів файлів. Для кожного файлу, що відкривається, потрібен дескриптор. Навіть при досить щедрому виділенні ресурсів файлові дескриптори в масштабі всієї системи можуть бути витрачені швидше, ніж ви можете собі уявити.
Linux абстрагує майже все, тому здається, що це файл. Іноді це просто старі файли. Але інші дії, такі як відкриття каталогу також використовують дескриптор файлу. Linux використовує спеціальні блокові файли в якості свого роду драйвера для апаратних пристроїв. Символьні спеціальні файли дуже схожі, але вони частіше використовуються з пристроями, що мають поняття пропускної спроможності, такі як канали та послідовні порти.
Спеціальні файли блоків обробляють блоки даних одночасно, а спеціальні файли символів обробляють кожен символ окремо. До цих спеціальних файлів можна отримати доступ тільки за допомогою файлових дескрипторів. Бібліотеки, які використовуються програмою, використовують дескриптор файлу, потоки використовують дескриптор файлу, а мережеві підключення використовують дескриптор файлу.
Абстрагування всіх цих різних вимог так, щоб вони відображалися у вигляді файлів, спрощує взаємодію з ними та дозволяє працювати таким речам, як конвеєри та потоки.
Ви можете бачити, що за лаштунками Linux відкриває файли і використовує файлові дескриптори тільки для запуску – не кажучи вже про ваші процеси користувача. Кількість відкритих файлів – це не просто кількість файлів, які ви відкрили. Багато операційної системи використовує дескриптори файлів.
Обмеження дескриптора файлу
За допомогою цієї команди можна побачити максимальну кількість дескрипторів файлів.
cat /proc/sys/fs/file-max
Це показує безглуздо велике число 9,2 квінтильйону. Це теоретичний максимум системи. Це максимально можливе значення, яке ви можете зберігати у 64-бітному цілому числі зі знаком. Чи зможе ваш бідний комп’ютер впоратися з такою кількістю файлів, відкритих одночасно, це зовсім інше питання.
На рівні користувача немає явного значення максимальної кількості відкритих файлів, які ви маєте. Але ми можемо приблизно це вирішити. Щоб дізнатися максимальну кількість файлів, які може відкрити один з процесів, ми можемо використовувати команду ulimit з параметром -n (відкрити файли).
ulimit -n
І щоб знайти максимальну кількість процесів, які може мати користувач, ми будемо використовувати ulimit з параметром -u (користувацькі процеси).
ulimit -u
Множення 1024 на 7640 дає 7823360. Звичайно, багато з цих процесів вже використовуються вашим середовищем робочого столу та іншими фоновими процесами. Так що це ще один теоретичний максимум, якого ви ніколи не досягнете.
Важливою цифрою є кількість файлів, які можуть відкрити процес. За замовчуванням це 1024. Варто відзначити, що відкриття одного і того ж файлу 1024 рази одночасно рівнозначне одночасного відкриття 1024 різних файлів. Як тільки ви витратите всі свої файлові дескриптори, все готово.
Можна настроїти кількість файлів, які можуть відкрити процес. Насправді, є два значення, які слід враховувати при налаштуванні цього числа. Одним з них є значення, яке встановлено зараз або яке ви намагаєтеся встановити. Це називається м’яким лімітом. Також існує жорстка межа, і це максимальне значення, до якого ви можете підняти м’яку межу.
Про це можна думати так: м’яке обмеження насправді є «поточним значенням», а верхня межа — це максимальне значення, якого може досягти поточне значення. Звичайний користувач без повноважень root може підняти м’який ліміт до будь-якого значення аж до свого жорсткого ліміту. Користувач root може збільшити жорсткий ліміт.
Щоб побачити поточні м’які та жорсткі обмеження, використовуйте ulimit із параметрами -S (м’який) та -H (жорсткий), а також із параметром -n (відкриті файли).
ulimit -Sn
ulimit -Hn
Щоб створити ситуацію, в якій ми можемо бачити застосування м’якого обмеження, ми створили програму, яка багаторазово відкриває файли, доки не відбудеться збій. Потім він чекає натискання клавіші, перш ніж відмовитись від всіх використовуваних файлових дескрипторів. Програма називається open-files.
./open-Files
Він відкриває файл 1021 і зазнає невдачі при спробі відкрити файл 1022.
1024 мінус 1021 дорівнює 3. Що сталося з рештою трьох дескрипторів файлів? Вони використовувалися для потоків STDIN, STDOUT та STDERR. Вони створюються автоматично кожного процесу. Вони завжди мають значення дескриптора файлу 0, 1 та 2.
Ми можемо побачити їх за допомогою команди lsof із параметром -p (процес) та ідентифікатором процесу програми open-files. Зручно, що він виводить свій ідентифікатор процесу у вікно терміналу.
lsof -p 11038
Звичайно, в реальній ситуації ви можете не знати, який процес щойно зжер всі дескриптори файлів. Щоб почати розслідування, можна використовувати цю послідовність команд. Він розповість вам про п’ятнадцять найактивніших користувачів файлових дескрипторів на вашому комп’ютері.
lsof | awk '{ print $1 " " $2; }' | sort -rn | uniq -c | sort -rn | head -15
Щоб переглянути більше або менше записів, змініть параметр -15 на команду head. Після того, як ви ідентифікували процес, вам потрібно з’ясувати, чи він шахрайський і відкриває занадто багато файлів, тому що він вийшов з-під контролю, або йому дійсно потрібні ці файли. Якщо вони потрібні, вам потрібно збільшити ліміт дескрипторів файлів.
Збільшення м’якого ліміту
Якщо ми збільшимо м’яке обмеження і запустимо нашу програму, ми повинні побачити, що вона відкриває більше файлів. Ми будемо використовувати команду ulimit та параметр -n (відкриті файли) з числовим значенням 2048. Це буде нова м’яка межа.
ulimit -n 2048
На цей раз ми успішно відкрили 2045 файлів. Як і очікувалося, це на три менше, ніж 2048, через дескриптори файлів, що використовуються для STDIN, STDOUT і STDERR.
Внесення постійних змін
Збільшення м’якого ліміту впливає лише на поточну оболонку. Відкрийте нове вікно терміналу та перевірте м’яке обмеження. Ви побачите, що це старе значення за промовчанням. Але є спосіб глобально встановити нове значення за замовчуванням для максимальної кількості відкритих файлів, які можуть мати процес, який буде постійним і витримає перезавантаження.
Застарілі поради часто рекомендують редагувати такі файли, як “/etc/sysctl.conf” та “/etc/security/limits.conf”. Однак у дистрибутивах на основі systemd ці зміни не працюють послідовно, особливо для графічних сеансів входу до системи.
Показана тут техніка це спосіб зробити це в дистрибутивах на основі systemd. Нам потрібно працювати із двома файлами. Перший – це файл “/etc/systemd/system.conf”. Нам потрібно буде використовувати sudo.
sudo gedit /etc/systemd/system.conf
Знайдіть рядок, який містить рядок “DefaultLimitNOFILE”. Видаліть решітку «#» на початку рядка та змініть перше число на те, що ви хочете, щоб було нове м’яке обмеження для процесів. Ми вибрали 4096. Друге число у цьому рядку – жорстка межа. Це ми не регулювали.
Збережіть файл та закрийте редактор.
Нам потрібно повторити цю операцію з файлом /etc/systemd/user.conf.
sudo gedit /etc/systemd/user.conf
Внесіть ті самі зміни до рядка, який містить рядок “DefaultLimitNOFILE”.
Збережіть файл та закрийте редактор. Ви повинні або перезавантажити комп’ютер, або використовувати команду systemctl з опцією daemon-reexec, щоб запустити systemd повторно та прийняти нові налаштування.
sudo systemctl daemon-reexec
Відкриття вікна терміналу та перевірка нової межі мають показати нове значення, яке ви встановили. У нашому випадку це було 4096.
ulimit -n
Ми можемо перевірити, чи це живе, робоче значення, повторно запустивши нашу файлово-жадібну програму.
./open-Files
Програма не може відкрити файл із номером 4094, тобто було відкрито 4093 файли. Це наше очікуване значення на 3 менше 4096.
Ось чому Linux залежить від дескрипторів файлів. Тепер, якщо вони почнуть закінчуватися, ви знаєте, як збільшити свою квоту.