Продолжаем разбирать systemd на кирпичики. Сегодня про кандишены (условия/ситуации).
Директива ConditionPathExists используется в юнит-файлах systemd и позволяет задать условие для запуска юнита: он будет запущен только если указанный файл или директория существует.
Пример:
[Unit]
Description=Special Service
ConditionPathExists=/etc/bashdays-config
[Service]
ExecStart=/usr/local/bin/bashdays-handler
Этот юнит не запустится, если файл /etc/bashdays-config не существует. В статусе сервиса ты увидишь:
ConditionPathExists=/etc/bashdays-config was not met
Если путь НЕ существует, systemd не будет запускать юнит. Вместо этого он будет считаться пропущенным (skipped), а не проваленным.
Нахуя это надо?
Например, если
bashdays-configсуществует, запускается сервис с особым поведением.Можно создавать один юнит, который активируется только при наличии определённого модуля или плагина.
Иногда это используют в early boot-юнитах, чтобы запускать их только если что-то доступно (например, том LUKS).
Список основных Condition’s
ConditionPathExists— файл или каталог существуетConditionPathIsDirectory— путь существует и это каталогConditionPathIsMountPoint— путь является точкой монтированияConditionFileIsExecutable— файл существует и он исполняемыйConditionKernelCommandLine— есть ли параметр ядра с указанным значениемConditionPathExistsGlob— совпадает ли хотя бы один путь по glob-шаблонуConditionPathIsSymbolicLink— является ли путь символической ссылкойConditionFileNotEmpty— существует ли файл и не пуст ли онConditionEnvironment— установлена ли переменная окруженияConditionArchitecture— архитектура CPU (например, x86_64, aarch64)ConditionVirtualization— nип виртуализации (например, kvm, docker)ConditionHost— имя хостаConditionMachineID— cовпадает ли machine-idConditionControlGroupController— есть ли указанный cgroup controller (например, cpu, memory)ConditionNeedsUpdate— нуждается ли в обновлении (/usr или /etc)ConditionFirstBoot— Первый ли это запуск после установкиConditionACPower— Подключено ли питание от сети (для ноутбуков)ConditionSecurity— Активен ли определённый LSM (например, selinux)ConditionUser— Запускается ли от указанного пользователяConditionGroup— Запускается ли от указанной группыConditionCapability— Имеет ли процесс определённую capabilityConditionNetwork— Есть ли сеть (online, configured)ConditionMemory— Есть ли минимум указанного объёма памяти
Дополнительно
Если заменить Condition на Assert, условие не выполнено — юнит считается проваленным, а не пропущенным.
То есть берем к примеру директиву ConditionPathExists и меняем её на AssertPathExists.
AssertPathExists=/etc/bashdays.conf
И получается:
ConditionPathExists — юнит пропускается (не считается ошибкой)
AssertPathExists — юнит падает (считается ошибкой)
Assert полезен, когда ты строго требуешь, чтобы ресурс (например, внешний диск, NFS, или другой том) был смонтирован перед запуском сервиса. Если его нет — это ошибка, а не «ну и похуй».
[Unit]
Description=Start backup script only if /mnt/backup is mounted
AssertPathIsMountPoint=/mnt/backup
[Service]
ExecStart=/usr/local/bin/backup.sh
Если /mnt/backup не смонтирован, systemd выдаст ошибку, и сервис не запустится.
Статус будет такой:
systemd[1]: Starting backup.service...
systemd[1]: backup.service: Failed with result 'assert'.
Ну и все это дело можно комбинировать:
ConditionPathExists=/mnt/backup
AssertPathIsMountPoint=/mnt/backup
Если /mnt/backup не существует — юнит пропускается.
Если существует, но не смонтирован — юнит заваливается.
systemd не такой уж простой, как кажется с первого взгляда. На нём можно прям заебись логику построить и получить желаемое. Так что недооценивать его явно не стоит, это прям заебись комбайн.







Комментарии