Центр Диагностики & База Системных Ошибок

Решения для Windows Server, Active Directory, 1С, СУБД, Linux, Cisco, MikroTik и IP-телефонии.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, баз данных и сетевого оборудования. Перед выполнением действий обязательно создайте резервную копию. При отсутствии необходимой квалификации обратитесь к ИТ-специалистам.
Cannot add dependency job for unit: Circular dependency detected Linux / DevOps

Found ordering cycle on basic.target — Циклические зависимости systemd

Обновлено: 18.08.2026  ·  Официальная база знаний

Архитектура ошибки и симптомы сбоя

Сообщение «Cannot add dependency job for unit: Circular dependency detected» (или «systemd[1]: Found ordering cycle on basic.target/start») генерируется планировщиком графов systemd Dependency Graph Engine. Ошибка означает, что в конфигурациях служб создана кольцевая логическая зависимость (Deadlock Cycle). Например: Сервис A настроен запускаться После Сервиса B (After=B.service), а Сервис B настроен запускаться После Сервиса A (After=A.service). Планировщик systemd не может построить линейную последовательность запуска и аварийно вырезает случайные критические юниты из графа.

Диагностическая таблица параметров сбоя

ПараметрЗначениеИнженерный смысл сбоя
Ordering CycleDirected Graph LoopЗамкнутый цикл между директивами Before= и After=.
Breaking Cycle ActionJob Deletionsystemd принудительно удаляет один из конфликтующих юнитов (часто sysinit.target или сетевой стек).
DefaultDependenciesimplicit After=basic.targetПо умолчанию все сервисы неявно запускаются ПОСЛЕ basic.target.

Пошаговое дерево решений и сценарии траблшутинга

Сценарий 1: Локализация точной петли зависимостей через systemd-analyze

# Проверка валидности всех установленных сервисов на предмет циклов:
sudo systemd-analyze verify /etc/systemd/system/*.service

# Поиск сообщений о разрыве циклов в системном логе:
sudo journalctl -b -p warning..emerg | grep -i -E "(cycle|breaking|deleting job)"

Сценарий 2: Распутывание классического конфликта раннего запуска (DefaultDependencies)

Если низкоуровневый сервис (ранний драйвер, VPN до сети, генератор ключей) требует запуска ДО basic.target:

# В unit-файле раннего сервиса ОБЯЗАТЕЛЬНО отключите дефолтные зависимости:
[Unit]
Description=Early Boot Custom Service
DefaultDependencies=no
After=sysinit.target
Before=basic.target

# Без директивы DefaultDependencies=no возникнет гарантированный ordering cycle!

Сценарий 3: Построение графического дерева зависимостей

# Экспорт графа зависимостей в формат SVG (требуется пакет graphviz):
systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target' | dot -Tsvg > /tmp/boot_graph.svg

Сценарий 4: Применение изменений и перезагрузка планировщика

# Перезагрузка графа юнитов ядра systemd:
sudo systemctl daemon-reload
Службы запускаются хаотично или отваливаются при загрузке из-за ordering cycles?
ITSTM проведет комплексный аудит unit-файлов, распутает графы зависимостей и выстроит детерминированный порядок инициализации.
Практический опыт инженера: При написании скриптов инициализации для монтирования сетевых дисков (Ceph, GlusterFS, iSCSI) никогда не указывайте одновременно Before=local-fs.target и After=network-online.target — это классическая циклическая ошибка.

Частые вопросы (FAQ)

Что такое DefaultDependencies=yes в systemd?

По умолчанию systemd неявно добавляет каждому сервису зависимости Requires=basic.target, After=basic.target и Before=shutdown.target. Если ваш сервис сам нужен для старта basic.target, возникает кольцевая зависимость.

Как systemd решает, какой юнит удалить при обнаружении цикла?

Алгоритм systemd удаляет случайную транзакционную задачу (Job) из петли. Часто жертвой становится базовая системная цель (например, sysinit.target/start), что приводит к полной недоступности дисков или сети.

В чем разница между Requires= и After=?

Requires= задает жесткую зависимость по наличию сервиса (если сервис B упал, сервис A не запустится). After= задает строго временной порядок старта (сервис A стартует строго после того, как сервис B начал работу).

Может ли директива Wants= вызвать циклический конфликт?

Сама директива Wants= (мягкая зависимость) циклов не создает, но в комбинации с противоречивыми директивами Before= и After= она формирует неразрешимый граф.