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

Linux: Too many links (EMLINK) на ext4/XFS — причины и рабочие обходы

EMLINK «Too many links» появляется внезапно: в CI при деплое, при rsync --link-dest, cp -al или распаковке архивов. Разберём лимит hard links на ext4/XFS, как найти inode-виновника и что менять в процессе.
Linux: Too many links (EMLINK) на ext4/XFS — причины и рабочие обходы

Что значит ошибка Too many links / EMLINK

Сообщение Too many links (errno EMLINK) в Linux почти всегда означает одно: вы пытаетесь создать ещё одну жёсткую ссылку (hard link) на inode, у которого уже достигнут предел счётчика ссылок (inode link count).

В отличие от проблем с правами, «слишком длинного пути» или переполненного диска, это именно ограничение файловой системы на количество имён, указывающих на один и тот же inode.

Типовой сценарий из продакшена: деплой делает «атомарные» релизы через hard link (или через snapshot-папки), чтобы не копировать гигабайты. На очередном прогоне CI всё внезапно падает с ln: failed to create hard link ...: Too many links или аналогичной ошибкой в cp/rsync/tar.

Важно: EMLINK — это не про количество файлов в каталоге и не про symlink. Это про счётчик жёстких ссылок на конкретный inode.

Быстрый ликбез: hard link vs symlink и где здесь лимит

Hard link — это ещё одно имя для того же inode (того же файла). Данные на диске общие: меняете файл по одному имени — изменения видны по всем именам, потому что inode один.

Symlink — это отдельный маленький файл-указатель на путь. У symlink нет общего inode с целью, поэтому он не упирается в hardlink-лимит, но может «отваливаться» при перемещениях и требует аккуратности со структурой путей.

Ограничение, о которое вы бьётесь, — максимальное число hard links на один inode. На практике чаще всего встречается:

  • ext4: типичный лимит жёстких ссылок на файл около 65 535 (в логах/обсуждениях часто называют «ext4 hlink limit»).
  • XFS: в большинстве случаев лимит «на бумаге» гораздо выше, но реальная проблема всё равно может проявляться как EMLINK (в зависимости от версии ядра/утилит и сценария), либо как сопутствующие сбои в инструментах, которые пытаются переносить/упаковывать дерево с большим количеством hard links.

Отдельная деталь: у каталогов тоже есть link count (из-за . и записей .. в подкаталогах). Но классический EMLINK в деплое почти всегда относится к файлам, а не к каталогам.

Схема inode и множества жёстких ссылок, объясняющая причину EMLINK

Почему это всплывает в CI/deploy: rsync --link-dest, cp -al и «релизы»

Почти всегда проблема не в «случайной ошибке ФС», а в схеме, которая многократно переиспользует один и тот же inode.

1) rsync --link-dest

Опция --link-dest делает «инкрементальные» копии: новые/изменённые файлы копируются, а неизменённые — связываются hard link’ом на файлы из базового каталога. Это экономит место и время, но увеличивает link count у популярных файлов.

Если вы много раз делаете инкремент в один и тот же «эталон» (или у вас цепочка, где один и тот же файл постоянно переиспользуется), то один «топовый» файл может набрать десятки тысяч ссылок. Частые кандидаты — одинаковые vendor-бандлы, зависимости, статические ассеты, сборочные артефакты.

2) cp -al

cp -al SRC DST создаёт дерево каталогов, где файлы — hard links на исходные. Это популярно в «release-based deploy» (папки releases/2026-...), чтобы быстро создать новый релиз.

Если вы храните сотни/тысячи релизов и каждый раз «линкуете» один и тот же набор файлов, hardlink-лимит становится вопросом времени.

3) Архивы и бэкапы: hard links внутри tar

tar умеет сохранять hard links внутри архива. При распаковке он попытается восстановить hard links — и если лимит достигнут, получите EMLINK во время распаковки/восстановления.

Особенно неприятно это проявляется в бэкапах, которые «кажутся обычными»: вы ожидали, что там просто файлы, а внутри оказалась сетка hard links (например, бэкап делали тем же rsync --link-dest или с rsync -H).

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

Как диагностировать: где именно набрался лимит ссылок

Задача диагностики — найти inode с большим link count и понять, какой процесс размножает ссылки.

Шаг 1. Найти файлы с большим числом ссылок

find умеет фильтровать по количеству hard links:

find /path/to/releases -xdev -type f -links +1000 -printf '%n %p\n' | sort -nr | head

Здесь %n — это inode link count. Порог +1000 поднимайте, если дерево большое.

Шаг 2. Убедиться, что это один inode

Посмотрите inode и число ссылок:

stat -c 'inode=%i links=%h path=%n' /path/to/suspect/file

Чтобы найти другие имена того же inode в пределах файловой системы, ищите по inode:

inode=$(stat -c '%i' /path/to/suspect/file); find /path/to/releases -xdev -inum "$inode" -print | head

Если вывод огромный — вы нашли «размноженный» inode и понимаете, почему достигли лимита.

Шаг 3. Поймать источник создания hard links

В CI источник обычно виден по логу команд (cp -al, rsync --link-dest, rsync -H, распаковка архива). На живой системе полезно:

  • пробежаться поиском по деплой-скриптам и job’ам CI на предмет флагов про hard links;
  • проверить политику хранения релизов/снимков: «хранить бесконечно» почти гарантированно приведёт к EMLINK.

Если вы используете дисковые квоты или алерты по ресурсам, полезно также мониторить аномально высокий link count в релизных/бэкапных деревьях. См. практику в статье про квоты и алерты на ext4/XFS.

Чем ext4 отличается от XFS в контексте hardlink limit

ext4 — самый предсказуемый случай: на обычных настройках вы упираетесь в лимит порядка 65k hard links на inode. Это ограничение реализации файловой системы, и «подкрутить sysctl» тут нельзя.

XFS обычно лучше справляется с большими деревьями и метаданными, но это не означает «можно бездумно плодить hard links». В реальных пайплайнах часто бывает так:

  • на ext4 вы падаете «быстро и честно» с EMLINK;
  • на XFS ошибка проявляется позже или в другом месте (например, при переносе/архивации/восстановлении), потому что схема в целом становится сложной и хрупкой.

Практический вывод: если схема деплоя/бэкапа концептуально «размножает один inode тысячами имён», лучше исправлять схему, а не надеяться на конкретную ФС. Если выбираете ФС под VDS и хотите понимать, где сильные стороны ext4 и XFS, полезно сравнение в материале ext4 vs XFS для VDS и тюнинг под нагрузку.

Рабочие обходы и исправления (по приоритету)

1) Ограничить количество релизов/снапшотов

Самый простой и часто самый правильный фикс: хранить ограниченное число релизов (например, 10–30) и чистить старые. Тогда inode link count не растёт бесконечно.

Проверьте, есть ли у вас:

  • папка releases/ с сотнями каталогов;
  • инкрементальные бэкапы rsync --link-dest без ротации;
  • сборочные артефакты, которые «линкуются» в каждый релиз.

2) Не hardlink’ать «тяжёлые» каталоги: vendor/node_modules/build

Частая ошибка — делать hardlink всего дерева проекта, включая зависимости. Но зависимости обычно можно доставлять иначе:

  • собирать артефакт (например, tar.gz) один раз и раскатывать как обычную копию без hard links;
  • кешировать зависимости в CI, но на сервер деплоя выкладывать «готовый результат»;
  • держать зависимости вне релизов и подключать через symlink на общий каталог (только если у вас хорошо контролируются версии и совместимость).

Да, это может добавить времени на деплой, но убирает класс ошибок EMLINK целиком.

3) Настроить rsync --link-dest так, чтобы база не была «вечной»

Если вы используете rsync --link-dest для бэкапов, то типовой паттерн — «сегодняшний» каталог как полноценный снимок, но фактически он состоит из hard links на «вчерашний». Важно, чтобы цепочка не опиралась на один и тот же неизменный inode годами.

Практичные приёмы:

  • ротация (daily/weekly/monthly) с удалением старых снимков;
  • периодический «полный» снимок без hard links (дороже по месту, но снимает накопление ссылок).

Логи CI/deploy с ошибкой Too many links и шаги диагностики

4) В деплое заменить cp -al на «копировать только нужное»

Если деплой сейчас делает новый релиз через cp -al, подумайте о модели:

  • хранить релиз как распакованный артефакт (обычные файлы);
  • использовать rsync без --link-dest на релизной папке;
  • выкатывать образ/контейнер (если это подходит проекту и инфраструктуре).

Смысл один: перестать увеличивать inode link count на одних и тех же файлах при каждом релизе.

5) Проверить, не создаёте ли вы hard links «случайно»

Иногда EMLINK появляется не из-за осознанного cp -al, а из-за того, что в пайплайн добавили сохранение/восстановление hard links:

  • rsync -H (сохранять hard links при копировании);
  • распаковка tar-архива, содержащего hard links;
  • инструменты дедупликации, которые «экономят место», заменяя одинаковые файлы hard link’ами.

Если hard links не часть вашей архитектуры — проще их отключить, чем лечить последствия.

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

Мини-рунбук: типичный CI deploy error и что делать прямо сейчас

Если деплой уже падает, действуйте так:

  1. Найдите конкретный файл, на котором упало (из лога CI).

  2. Проверьте число ссылок:

    stat -c 'links=%h inode=%i %n' /path/to/file
  3. Если links очень большое — оцените масштаб размножения inode:

    inode=$(stat -c '%i' /path/to/file); find /path/to/releases -xdev -inum "$inode" | wc -l
  4. Срочно сократите число релизов/снимков (удалите старые) либо переключите деплой на обычное копирование для этого прогона.

  5. После восстановления сервиса — исправьте процесс: ротация релизов, пересборка артефактов, исключение зависимостей из hardlink-схемы.

Почему «просто увеличить лимит» нельзя

Вопрос «как увеличить hardlink limit» возникает всегда. В Linux это не sysctl и не лимит процесса — это ограничение формата/реализации файловой системы и поведения совместимых инструментов. Для ext4 это особенно жёстко: упёрлись — значит, архитектурно надо менять подход (ротация, отказ от hard links на горячем пути, другая модель деплоя/бэкапа).

Чеклист профилактики

  • Держите конечное число релизов и бэкап-снимков. «Храним всё» почти всегда заканчивается EMLINK или переполнением диска.

  • Не линковать hard link’ами каталоги зависимостей и сборочные output’ы, если релизов много.

  • Явно документируйте, где в инфраструктуре допускаются hard links: деплой, бэкап, дедупликация.

  • Периодически сканируйте на аномально большой inode link count в релизных/бэкапных деревьях.

Итог

Too many links/EMLINK — ожидаемый результат, когда схема деплоя или бэкапа слишком активно переиспользует один inode через hard links. На ext4 вы чаще упрётесь в предел около 65k, на XFS проблема может проявляться иначе, но суть та же: бесконтрольное размножение ссылок — это техдолг.

Самые надёжные решения: ротация релизов/снимков, отказ от hardlink-деревьев для зависимостей, и пересборка пайплайна так, чтобы он создавал артефакт и раскатывал его без «умной» дедупликации на файловой системе.

Если вы переносите проекты на отдельный сервер под CI/деплой или бэкапы, удобно держать это на VDS, чтобы гибко управлять дисками, ФС и политиками хранения.

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

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

systemd hardening: DynamicUser, ProtectSystem и практичный sandboxing для сервисов OpenAI Статья написана AI (GPT 5)

systemd hardening: DynamicUser, ProtectSystem и практичный sandboxing для сервисов

Пошагово усиливаем безопасность systemd-сервисов без контейнеров: включаем DynamicUser, ограничиваем файловую систему через Protec ...
JWT security: JWKS, key rotation, clock skew и защита от alg=none OpenAI Статья написана AI (GPT 5)

JWT security: JWKS, key rotation, clock skew и защита от alg=none

JWT удобны в микросервисах, но ошибки валидации быстро превращают их в дыру. Разберём JWKS и kid, ротацию ключей без даунтайма, уч ...
Segfault в production на Linux: coredumpctl, gdb и debuginfo — разбор падений без паники OpenAI Статья написана AI (GPT 5)

Segfault в production на Linux: coredumpctl, gdb и debuginfo — разбор падений без паники

Segfault в проде — это не «рандом», а нехватка артефактов. Показываю пошагово: включить core dump в systemd, проверить core_patter ...