На компьютерах с 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 дает 7 823 360. Конечно, многие из этих процессов уже используются вашей средой рабочего стола и другими фоновыми процессами. Так что это еще один теоретический максимум, которого вы никогда не достигнете.
Важной цифрой является количество файлов, которые может открыть процесс. По умолчанию это 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 так зависит от дескрипторов файлов. Теперь, если они у вас начнут заканчиваться, вы знаете, как увеличить свою квоту.