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), а не проваленным.Нахуя это надо?
1. Например, если
bashdays-config существует, запускается сервис с особым поведением.2. Можно создавать один юнит, который активируется только при наличии определённого модуля или плагина.
3. Иногда это используют в 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-id
ConditionControlGroupController — есть ли указанный cgroup controller (например, cpu, memory)
ConditionNeedsUpdate — нуждается ли в обновлении (/usr или /etc)
ConditionFirstBoot — Первый ли это запуск после установки
ConditionACPower — Подключено ли питание от сети (для ноутбуков)
ConditionSecurity — Активен ли определённый LSM (например, selinux)
ConditionUser — Запускается ли от указанного пользователя
ConditionGroup — Запускается ли от указанной группы
ConditionCapability — Имеет ли процесс определённую capability
ConditionNetwork — Есть ли сеть (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 не такой уж простой, как кажется с первого взгляда. На нём можно прям заебись логику построить и получить желаемое. Так что недооценивать его явно не стоит, это прям заебись комбайн.🛠 #linux #tricks #debug #systemd #bash
—
✅ @bashdays / @linuxfactory / @blog