Правильный синтаксис файла Systemd Unit для корректной работы команд

Вопрос или проблема

У меня есть этот скрипт, который работает:

#! /usr/bin/bash

export SEQVAL=$(date +%s) &&  sed -i "s/^SEQ1=.*$/SEQ1=${SEQVAL}/" /etc/environment
systemctl restart ccs-srvapp-telemetry.service

Хоть убей, не могу заставить это работать правильно из unit файла.

Последний вариант ниже, но было несколько попыток с различными настройками, все провалились из-за того, что либо переменная не устанавливалась, либо что-то не корректно экранировалось в команде sed.

[Unit]
Description=restarts fluent bit with a new SEQ1 to force a logrotate
After=network.target


[Service]
Type=oneshot
EnvironmentFile=/etc/environment
ExecStart=/usr/bin/sh -c 'export SEQVAL=$(date +%s) && sed -i "s/^SEQ1=.*$/SEQ1=${SEQVAL}/" /etc/environment'
ExecStartPost=/bin/systemctl restart ccs-srvapp-telemety.service


[Install]
WantedBy=multi-user.target

Нужно быть осторожным при использовании $ в строках Exec, так как systemd будет расширять форму ${variable} везде, где она встречается, даже внутри строки в одинарных кавычках. Чтобы этого избежать, экранируйте $ с помощью $$.
Также, % используется для спецификаторов, поэтому %s заменяется на имя оболочки. Экранируйте % с помощью %%.

ExecStart=/usr/bin/sh -c 'SEQVAL=$(date +%%s); sed -i "s/^SEQ1=.*/SEQ1=$${SEQVAL}/" /etc/environment'

но это тоже должно работать:

ExecStart=/usr/bin/sh -c 'sed -i "s/^SEQ1=.*/SEQ1=$(date +%%s)/" /etc/environment'

Также, учтите, что команды ExecStartPost могут быть запущены до завершения команды ExecStart. Они запускаются, когда команда инициирована. Если вы хотите быть уверены, что файл окружения обновлен, так как вы используете Type=oneshot, вы можете просто использовать несколько строк ExecStart, и они будут выполнены последовательно.

Ответ или решение

Вопрос о корректной синтаксической записи файла Systemd Unit, чтобы команды выполнялись ожидаемо, является типичной задачей для специалистов в области ИТ, особенно в контексте автоматизации и конфигурации систем. Чтобы достичь необходимого результата, важно уделить внимание деталям в корректировке синтаксиса и логики выполнения скриптов в файлах Unit.

Решение проблемы синтаксиса в файле Systemd Unit

Контекст проблемы

Имеется скрипт на Bash, который выполняет следующие действия:

  1. Устанавливает значение переменной SEQVAL, используя текущую временную метку.
  2. Обновляет файл окружения /etc/environment с новым значением SEQVAL.
  3. Перезапускает сервис ccs-srvapp-telemetry.service.

При переносе этого функционала в Unit-файл Systemd возникают ошибки с установкой переменной и корректным выполнением команды sed. Основная причина ошибок связана с тем, как Systemd обрабатывает символы $ и %.

Корректный синтаксис для Systemd Unit файла

Основные моменты
  1. Экранирование символов: Systemd автоматически интерпретирует ${variable} и %s, даже внутри одиночных кавычек. Чтобы этого избежать, используйте $$ для $ и %% для %.

  2. Выполнение команд: Команды в секции [Service] выполняются указанным шеллом, поэтому важно указать правильный шелл, если требуется конкретная интерпретация команд.

  3. Последовательность выполнения: С учетом того, что используется Type=oneshot, команды ExecStart выполняются последовательно, что устраняет необходимость в ExecStartPost для данной задачи.

Пример исправленного Unit-файла:
[Unit]
Description=Обновление SEQ1 и перезапуск fluent bit для принудительного вращения логов
After=network.target

[Service]
Type=oneshot
EnvironmentFile=/etc/environment
ExecStart=/usr/bin/sh -c 'SEQVAL=$(date +%%s); sed -i "s/^SEQ1=.*/SEQ1=$${SEQVAL}/" /etc/environment'
ExecStart=/bin/systemctl restart ccs-srvapp-telemetry.service

[Install]
WantedBy=multi-user.target

Пояснения

  • ExecStart и экранирование: Использование $$ вместо одного $ гарантирует, что переменная будет установлена корректно. Использование %% вместо % позволяет избежать подстановки имени шелла.

  • ExecStart вместо ExecStartPost: Достигается гарантированная последовательность выполнения команд, так как команды ExecStart выполняются одна за другой, и сервис не завершит выполнение, пока каждая из команд не завершится.

Заключение

Оптимизация файла Unit для Systemd требует внимания к деталям в синтаксисе и понимания механизмов работы Systemd. Правильное экранирование и организация команд внутри файла позволяют достичь желаемого результата без сбоев и ошибок.

Оцените материал
Добавить комментарий

Капча загружается...