Выберите продукт

Debian/Ubuntu: как исправить inotify limits, max_user_watches и Too many open files

Если webpack, Vite, VS Code, systemd path units или CI runner перестают следить за файлами в Debian/Ubuntu, причина часто в лимитах inotify или дескрипторов. Разберём, как быстро найти упёршийся лимит и поднять его аккуратно.
Debian/Ubuntu: как исправить inotify limits, max_user_watches и Too many open files

Ошибки вида ENOSPC: System limit for number of file watchers reached, Too many open files, watch ... failed или жалобы от webpack, vite, VS Code, jest --watch, nodemon, CI-раннеров и даже systemd.path в Debian/Ubuntu встречаются чаще, чем кажется. Обычно проблема не в самом приложении, а в системных лимитах Linux: закончились наблюдатели inotify, инстансы inotify или файловые дескрипторы.

Особенно заметно это на фронтенд-проектах с большим количеством файлов, в монорепозиториях, контейнерных окружениях, self-hosted CI и на серверах, где одновременно работают редакторы, сборщики, синхронизация кода и сервисы, отслеживающие изменения на диске.

Самое неприятное здесь — схожесть симптомов. Один инструмент пишет про watch, второй про ENOSPC, третий про EMFILE, а четвёртый просто перестаёт реагировать на изменения файлов. Поэтому сначала важно не поднимать всё подряд, а понять, какой именно лимит вы упёрли.

Что такое inotify и почему упираются именно в него

inotify — это механизм ядра Linux для отслеживания изменений в файловой системе. Его используют редакторы, IDE, фронтенд-сборщики, file watchers, агенты синхронизации, некоторые демоны и сервисы systemd. Когда приложение хочет следить за каталогом или файлом, оно создаёт watcher через inotify.

В Linux здесь важны три параметра:

  • fs.inotify.max_user_watches — сколько watcher-ов может создать один пользователь.
  • fs.inotify.max_user_instances — сколько inotify-инстансов может создать один пользователь.
  • fs.inotify.max_queued_events — размер очереди событий для inotify.

Отдельно от этого существует лимит открытых файловых дескрипторов — nofile. Именно он часто даёт ошибку Too many open files, и его очень легко перепутать с ограничениями inotify.

Если вы видите слово watch, это ещё не значит, что проблема именно в fs.inotify.max_user_watches. Наблюдатели файлов и открытые дескрипторы связаны по смыслу, но это разные лимиты.

Какие симптомы на что похожи

Есть несколько типовых сценариев, по которым можно быстро сузить круг поиска.

Когда не хватает max_user_watches

Обычно это происходит в больших проектах: много директорий, много файлов, много подпапок в node_modules, несколько процессов в режиме watch. Частые сообщения выглядят так:

ENOSPC: System limit for number of file watchers reached
Error: watch ... ENOSPC

Такое часто встречается в сценариях webpack watch linux, vite watch limit, vscode inotify limit.

Когда не хватает max_user_instances

Здесь watcher-ов может быть не так много, но слишком много отдельных процессов создают собственные inotify-инстансы. Например, открыто несколько окон IDE, терминалы с дев-серверами, синхронизация, тесты в watch-режиме, агент CI и фоновые утилиты.

Типичный симптом — приложение не может создать новый экземпляр inotify, хотя часть слежения уже работает.

Когда проблема в nofile

Если сообщение выглядит как Too many open files, EMFILE или сервис не может открыть новый файл, сокет или лог, смотрим в сторону лимита дескрипторов. Это особенно актуально для CI, Node.js, reverse proxy, процессов с большим числом соединений и контейнерных раннеров.

Ключевой момент: увеличение fs.inotify.max_user_watches не лечит Too many open files, если у вас упёрся именно LimitNOFILE или пользовательский ulimit -n. Если тема systemd-лимитов нужна глубже, посмотрите и разберите отдельно настройку лимитов сервисов в systemd.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Для таких задач особенно удобен сервер, где вы полностью контролируете sysctl, systemd и пользовательские лимиты. На практике подобные проблемы проще диагностировать на VDS, чем в жёстко ограниченном окружении.

Быстрая диагностика в Debian/Ubuntu

Начните с просмотра текущих значений sysctl:

sysctl fs.inotify.max_user_watches
sysctl fs.inotify.max_user_instances
sysctl fs.inotify.max_queued_events

Альтернативно можно читать значения напрямую из /proc:

cat /proc/sys/fs/inotify/max_user_watches
cat /proc/sys/fs/inotify/max_user_instances
cat /proc/sys/fs/inotify/max_queued_events

Теперь проверьте лимит открытых файлов в текущей сессии:

ulimit -n

Если проблема у systemd-сервиса, этого недостаточно. У процесса может быть свой лимит, не совпадающий с интерактивной оболочкой:

systemctl show your-service -p LimitNOFILE

Для уже работающего процесса можно посмотреть реальные лимиты так:

cat /proc/$(pgrep -n node)/limits
cat /proc/12345/limits

Как понять, что именно расходует inotify

Универсальной одной команды тут нет, но часто помогает оценка по открытым файловым дескрипторам и поиску inotify в /proc:

find /proc/*/fd -lname anon_inode:inotify 2>/dev/null | wc -l

Эта команда покажет общее количество открытых inotify-дескрипторов в системе. Для поиска процессов-источников:

for pid in /proc/[0-9]*; do n=$(find "$pid/fd" -lname anon_inode:inotify 2>/dev/null | wc -l); if [ "$n" -gt 0 ]; then printf "%s %s
" "$(basename "$pid")" "$n"; fi; done | sort -k2 -n

Если нужен вывод вместе с командной строкой процесса:

for pid in /proc/[0-9]*; do n=$(find "$pid/fd" -lname anon_inode:inotify 2>/dev/null | wc -l); if [ "$n" -gt 0 ]; then printf "%s %s " "$(basename "$pid")" "$n"; tr '\0' ' ' < "$pid/cmdline" 2>/dev/null; printf "
"; fi; done | sort -k2 -n

Это не даст точное число watcher-ов внутри каждого инстанса, но быстро покажет, кто плодит inotify-инстансы.

Как проверить ошибку Too many open files

Сначала посмотрите, сколько дескрипторов уже открыто у процесса:

ls /proc/12345/fd | wc -l

Потом сравните это с лимитом из /proc/12345/limits. Если значения близки, причину вы нашли.

Проверка значений fs.inotify.max_user_watches и связанных ошибок watch

Текущие настройки и порядок применения в Debian/Ubuntu

Когда администратор меняет sysctl и не видит результата после перезапуска сервиса, почти всегда проблема в порядке загрузки конфигурации или в том, что редактировался не тот слой настроек.

В актуальных Debian и Ubuntu параметры sysctl обычно применяются через systemd-sysctl. Это значит, что значения читаются из нескольких каталогов, а приоритет зависит от имени файла и места расположения.

Проверить применённые параметры можно так:

systemctl status systemd-sysctl
systemd-analyze cat-config sysctl.d

Второй вариант особенно полезен, если вы подозреваете, что какой-то пакет или automation уже прописал свои значения, а ваш файл перекрывается позже.

Если вас интересует тема systemd-sysctl inotify, правильный путь — не править одно и то же в нескольких местах, а держать один понятный override-файл в /etc/sysctl.d/.

Как безопасно увеличить fs.inotify.max_user_watches и max_user_instances

Для большинства рабочих станций разработчика, CI-раннеров и сборочных серверов лучше использовать отдельный файл в /etc/sysctl.d/, а не хаотично редактировать /etc/sysctl.conf.

Создайте файл конфигурации:

sudo sh -c 'cat > /etc/sysctl.d/60-inotify.conf <<"EOF"
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 1024
fs.inotify.max_queued_events = 32768
EOF'

Затем примените настройки:

sudo sysctl --system

И проверьте результат:

sysctl fs.inotify.max_user_watches
sysctl fs.inotify.max_user_instances
sysctl fs.inotify.max_queued_events

Почему именно такие значения? Это не магия и не универсальный стандарт, а практичный стартовый уровень. Значение 524288 для fs.inotify.max_user_watches и 1024 для fs.inotify.max_user_instances обычно покрывает крупные проекты с IDE и несколькими watch-процессами без заметного вреда для сервера.

Если у вас очень плотный CI, несколько runner-ов на одном хосте, большие монорепозитории или много контейнеров, можно поднять лимиты выше, но делать это стоит осознанно и после наблюдения за реальным потреблением.

Когда нужен reboot, а когда нет

Для параметров sysctl перезагрузка обычно не требуется. Достаточно sysctl --system. Но приложения, которые уже получили ошибку и вошли в деградировавшее состояние, иногда нужно перезапустить вручную.

  • IDE или remote server VS Code;
  • процессы vite, webpack, nodemon;
  • агенты CI и раннеры;
  • systemd-сервисы, которые работают с file watch.

Как исправить Too many open files отдельно от inotify

Если ваша ошибка — именно Too many open files или EMFILE, проверьте лимиты nofile для пользователя, systemd-юнита и, при необходимости, PAM-сессий.

Для systemd-сервиса

Создайте override:

sudo systemctl edit your-service

И добавьте в открывшийся файл:

[Service]
LimitNOFILE=262144

Затем выполните:

sudo systemctl daemon-reload
sudo systemctl restart your-service
systemctl show your-service -p LimitNOFILE

Для интерактивного пользователя

На системах с PAM можно задать лимиты в /etc/security/limits.d/:

sudo sh -c 'cat > /etc/security/limits.d/60-nofile.conf <<"EOF"
* soft nofile 65535
* hard nofile 262144
EOF'

После этого обычно требуется новая сессия входа. Для SSH — переподключиться, для графической сессии — перелогиниться.

Если сервис запускается через systemd, приоритетнее смотреть именно на LimitNOFILE в unit-файле, а не только на limits.conf.

Когда ошибки упираются не только в inotify, но и в ресурсы юнита в целом, полезно дополнительно проверить лимиты процесса, CPU и память. Для этого пригодится статья про настройку ограничений systemd-сервисов.

Практические сценарии: webpack, Vite, VS Code, CI runner

webpack watch linux

Если webpack --watch внезапно перестал видеть изменения или валится с ENOSPC, почти всегда упёрлись в fs.inotify.max_user_watches. Особенно часто это проявляется в монорепах и проектах с несколькими пакетами.

Поднимите max_user_watches, затем перезапустите процесс сборки. Если ошибка не исчезла и теперь вы видите EMFILE, значит второй потолок — это уже nofile.

vite watch limit

Vite чувствителен к окружению разработки и особенно к bind mount в контейнерах, WSL-подобным сценариям и большим директориям. На нативном Linux проблема обычно решается увеличением inotify-лимитов. Но если проект крутится в контейнере, учитывайте, где именно живёт watcher: внутри контейнера или на хосте.

Если рантайм контейнера наследует ограничения хоста, чинить нужно в первую очередь сам хост Debian/Ubuntu.

vscode inotify limit

VS Code, особенно с расширениями, remote development и несколькими workspace, быстро расходует watcher-ы. Пользователь видит, что поиск работает, но автоперезагрузка, диагностика или отслеживание изменений начинают вести себя нестабильно.

Здесь хорошо помогает увеличение fs.inotify.max_user_watches и fs.inotify.max_user_instances одновременно, потому что IDE нередко создаёт много отдельных наблюдателей и процессов.

ci runner inotify

Self-hosted runner-ы для CI/CD часто запускают параллельные job, сборки фронтенда, тесты в watch-режиме, линтеры и кэширующие процессы. Если несколько pipeline работают одновременно, упереться можно и в inotify, и в nofile.

В таких сценариях рекомендую действовать так:

  1. Сначала зафиксировать текущие лимиты и реальное потребление.
  2. Поднять fs.inotify.max_user_watches и fs.inotify.max_user_instances умеренно, а не на максимум.
  3. Для runner-сервиса отдельно проверить LimitNOFILE.
  4. Ограничить параллелизм, если проблема вызвана не лимитами, а архитектурой job.

Для инфраструктуры, где часто нужны такие ручные настройки, удобнее использовать VDS для CI и сборочных задач с полным доступом к системным параметрам.

Диагностика LimitNOFILE и ошибки Too many open files в systemd

Почему не стоит бездумно ставить огромные значения

В интернете часто советуют поставить fs.inotify.max_user_watches = 1048576 или даже больше и забыть. Иногда это нормально, но без контекста такой совет плох.

Каждый watcher потребляет память ядра. На современной машине это редко становится катастрофой само по себе, но на маленьком сервере с несколькими тяжёлыми сервисами бессмысленное завышение лимитов — не лучшая идея. Особенно если первопричина в runaway-процессе, утечке watcher-ов или слишком агрессивном CI.

Хорошая практика — поднять лимит до разумного уровня, проверить, ушла ли проблема, и через несколько дней посмотреть, не растёт ли потребление снова.

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Что делать, если после повышения лимитов проблема осталась

Если вы уже изменили fs.inotify.max_user_watches и fs.inotify.max_user_instances, а ошибка не ушла, проверьте следующие моменты:

  • Настройки действительно применились через sysctl --system.
  • Нужный процесс был перезапущен после изменения.
  • Ошибка на самом деле не про nofile.
  • Проблема возникает внутри контейнера, а меняете вы хост или наоборот.
  • Есть process leak: старые dev-server или IDE-сессии висят в фоне и продолжают держать watcher-ы.
  • У вас не inotify-проблема, а особенности сетевой ФС, bind mounts или синхронизации файлов.

Для быстрой санитарной проверки полезно закрыть лишние IDE, остановить старые watch-процессы и повторно проверить число inotify-дескрипторов.

Рекомендуемые значения для типовых сценариев

Абсолютных значений нет, но как практическая отправная точка можно использовать такие ориентиры.

Ноутбук разработчика или dev VM

  • fs.inotify.max_user_watches = 262144 или 524288;
  • fs.inotify.max_user_instances = 512 или 1024;
  • nofile для пользователя от 65535.

Сервер сборки или CI runner

  • fs.inotify.max_user_watches = 524288 или выше по факту нагрузки;
  • fs.inotify.max_user_instances = 1024;
  • LimitNOFILE для runner-сервиса от 131072 или 262144.

Небольшой production-сервер

Если там нет IDE, фронтенд-сборки и file-watch workload, поднимать inotify про запас обычно не нужно. Но если на сервере крутится deploy-agent, watcher-based синхронизация или systemd.path-юниты, умеренное увеличение тоже бывает полезно.

Если вам нужен сервер под такие кастомные сценарии с полным доступом к системным параметрам, разумно сразу брать VDS для Linux-проектов, а не среду, где системные лимиты менять нельзя.

Минимальный рабочий runbook

Если нужен короткий и безопасный план действий, используйте такой порядок:

  1. Считать текущие значения fs.inotify.max_user_watches, fs.inotify.max_user_instances и ulimit -n.
  2. Понять тип ошибки: ENOSPC или EMFILE.
  3. Создать override в /etc/sysctl.d/60-inotify.conf.
  4. Применить sysctl --system.
  5. При необходимости поднять LimitNOFILE у нужного systemd-сервиса.
  6. Перезапустить проблемный процесс.
  7. Проверить, не осталось ли фоновых watcher-процессов.

Вывод

Ошибки fs.inotify.max_user_watches, fs.inotify.max_user_instances, Too many open files и любые сообщения про watch в Debian/Ubuntu — это типичная админская рутина, но решается она не угадыванием, а аккуратной диагностикой. Сначала различаем inotify и nofile, потом проверяем реальные лимиты процесса, затем вносим изменения через /etc/sysctl.d/ и systemd override.

Если делать именно так, а не копировать случайные команды из форумов, проблема обычно уходит быстро и не возвращается при следующем запуске webpack, Vite, VS Code или CI runner.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: как исправить ext4 orphan inodes и journal checksum errors OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить ext4 orphan inodes и journal checksum errors

Если в Debian или Ubuntu ext4 внезапно монтируется только для чтения, а в логах видны orphan inodes, journal checksum error и corr ...
Debian/Ubuntu: как исправить curl error 6 Could not resolve host и проблемы с DNS OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить curl error 6 Could not resolve host и проблемы с DNS

Если в Debian или Ubuntu команда curl отвечает ошибкой error 6 Could not resolve host, причина почти всегда связана с DNS: сломан ...
Debian/Ubuntu: systemd Failed to set up mount namespacing и sandboxing — как исправить OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: systemd Failed to set up mount namespacing и sandboxing — как исправить

Ошибка systemd Failed to set up mount namespacing в Debian/Ubuntu часто появляется после включения ProtectSystem, ProtectHome, Pri ...