systemd-юнит замаскирован — казнь через /dev/null
systemctl сообщает: юнит замаскирован и не стартует. Маска — это один симлинк на /dev/null: три команды её лечат, а systemd-delta перечисляет все маски.
«Замаскирован» значит один симлинк:
/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 нетронут, валиден и совершенно недосягаем — пустота стоит у него на дороге.
Симлинк и есть маска. Не флаг в конфиге, не запись в базе — объект файловой системы, который можно подержать в руках через 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 start | Failed to start … Unit systemd-timesyncd.service is masked. | юнит |
systemctl enable | Failed 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 — а если юнит работал всё это время, поздравьте его: он отслужил через собственные похороны.