SYSTEMD · 2026-11-06

systemd-юнит замаскирован — казнь через /dev/null

systemctl сообщает: юнит замаскирован и не стартует. Маска — это один симлинк на /dev/null: три команды её лечат, а systemd-delta перечисляет все маски.

HUMANавтор @mrkeepalive5h5 мин чтения

«Замаскирован» значит один симлинк: /etc/systemd/system/<unit>.service → /dev/null. Снесите симлинк (systemctl unmask), перечитайте конфигурацию (systemctl daemon-reload), запустите (systemctl start <unit>) — юнит поднимется. Полную опись масок даёт systemd-delta --type=masked.

Проверено на одноразовой VM с Arch Linux, cloud image, systemd 262; последняя проверка 2026-11-05. Каждая строка ниже взята из того прогона без единой правки.

Сентябрьский материал-побратим разбирал юниты, которые отказываются стартовать громко — сервис systemd не стартует: лог уже назвал причину. Замаскированный юнит — преступление наоборот. Здесь лог молчит, потому что сам лог — часть того, что замаскировали.

Почему systemctl называет мой юнит замаскированным?

Потому что systemctl mask — или кто бы ни накладывал маску — создал ровно один симлинк там, где должен быть локальный путь вашего юнита. Весь механизм исчерпывается этим. Запустите сами — systemd сознаётся обычными словами:

$ sudo systemctl mask systemd-timesyncd
Created symlink '/etc/systemd/system/systemd-timesyncd.service' → '/dev/null'.

Когда загрузчик получает команду стартовать юнит, он разрешает /etc/systemd/system/systemd-timesyncd.service, упирается в /dev/null, вместо определения юнита находит пустой файл — и отказывает:

$ sudo systemctl start systemd-timesyncd
Failed to start systemd-timesyncd.service: Unit systemd-timesyncd.service is masked.

systemctl is-enabled отвечает masked. Файл юнита в /usr/lib/systemd/system нетронут, валиден и совершенно недосягаем — пустота стоит у него на дороге.

systemctl start загрузчик юнитов разрешает/etc/systemd/system /dev/null — пустота настоящий файл юнита ждёт/usr/lib/systemd/system отказ, только stderr

Симлинк и есть маска. Не флаг в конфиге, не запись в базе — объект файловой системы, который можно подержать в руках через ls. Снесите его — и машина забудет, что маска вообще существовала.

Почему замаскированный юнит всё ещё работает?

Вот ловушка, съедающая полдня: замаскирован — не значит остановлен. Маска — это проверка при следующем start, enable или link. Всё, что уже живо, продолжает жить. Из того же стендового прогона, снято после маски:

$ systemctl status systemd-timesyncd --no-pager -n 0
● systemd-timesyncd.service
     Loaded: masked (Reason: Unit systemd-timesyncd.service is masked.)
     Active: active (running) since Thu 2026-11-05 05:10:21 UTC; 1min 28s ago
     Main PID: 320
     Status: "Contacted time server 213.219.38.86:123 (2.arch.pool.ntp.org)."

Loaded: masked и Active: active (running) — соседние строки, и оба факта верны разом. PID 320 все полторы минуты, пока существовала маска, продолжал обслуживать NTP — и продолжал бы до stop, restart или перезагрузки. Если ваш замаскированный юнит несёт нагрузку и вы рассчитывали, что маска его придержит, — не придержала. Останавливайте сами.

Почему в журнале нет ни одной строки об этом?

Потому что отказ пишется в ваш терминал, а не в журнал. Подсчёт свидетелей из стендового прогона — три минуты журнала вокруг маски:

$ sudo journalctl -u systemd-timesyncd --since '-3 min' --no-pager | wc -l
9

Девять строк в окне. Каждая — собственная болтовня работающего процесса, контакты с серверами времени. Ни одна строка не упоминает маску, ни одна — отказанный старт. Единственное административное событие, изменившее судьбу юнита, невидимо для самого первого инструмента, который вы откроете. /dev/null — это systemd подшивает юнит в папку выбыл, и пусть остаётся выбывшим — и рапорта не подаёт. Правда, называют два отказа разное — и в этом есть польза:

командачто печатаетчто называет
systemctl startFailed to start … Unit systemd-timesyncd.service is masked.юнит
systemctl enableFailed to enable unit: Unit /etc/systemd/system/systemd-timesyncd.service is maskedпуть симлинка

Start называет юнит; enable называет путь. Та же пустота, два алиби. Маска — единственная казнь на вашей машине, не оставляющая в журнале ни строки. Свидетель один: файловая система.

Как найти все замаскированные юниты на машине?

Одна команда описывает их все — systemd-delta, она сообщает о локальных переопределениях, включая роковую разновидность:

$ systemd-delta --type=masked
[MASKED]     /etc/systemd/system/systemd-timesyncd.service → /usr/lib/systemd/system/systemd-timesyncd.service

1 overridden configuration files found.

verify: systemd-delta --type=masked перечисляет все замаскированные юниты вместе с их настоящей целью — запускайте на любой машине, доставшейся вам по наследству.

systemctl list-unit-files --state=masked читает ту же правду из кэша файлов юнитов и отвечает числом. Обе команды сильнее grep -r по /etc/systemd/system, и обе умещаются в записку при передаче смены. Если вы администрируете машины, собранные чужими руками, запускайте delta, прежде чем поверить любому «сломанному» юниту — маска, оставленная hardening-скриптом или забытой войной с NTP-демоном, снаружи выглядит в точности как битый пакет.

Как размаскировать сервис systemd?

Три команды, по порядку:

verify: systemctl list-unit-files --state=masked → 0 unit files listed. — вот вылеченная машина, прямо из стендового прогона.

Без daemon-reload обычно прокатывает, но время от времени — нет. Перечитывание стоит секунду — потратьте её.

Кто наложил маску — и когда?

Честная опись: три вечных подозреваемых. Ваше же прошлое «я» (замаскировал при миграции и так и не вернулся), пакетная война (дистрибутивы маскируют NTP- или DNS-резолвер, который проиграли — именно этот юнит из стендового прогона, systemd-timesyncd, чаще прочих всплывает в поисковиках) и hardening-скрипты, маскирующие всё, чего не понимают. Ни один из троих не признаётся в журнале. Единственное заявление о намерениях, которое вам достанется, — собственная метка времени симлинка:

$ stat -c '%y %n' /etc/systemd/system/<unit>.service

Прежде чем размаскировать на общей машине, выполните это. Дата подскажет, что именно вы отменяете: вчерашний security-скрипт или войну, кем-то выигранную три года назад. Затем unmask, reload, start — а если юнит работал всё это время, поздравьте его: он отслужил через собственные похороны.