Выполнение команд в systemd unit

Systemd Unit - выполнение команд из юнита

Для чего это нужно?

Например у нас стоит следующая задача: написать Systemd Service Unit, который будет запускать приложение /usr/local/bin/node_exporter и нам необходимо, чтобы при этом соблюдались следующие условия:

  • node_exporter запускаться после готовности network.target;
  • запускаться от имени пользователя prometheus;
  • хранит PID файл в /var/run/node_exporter.pid;

Самым сложным вопросом в данной условиях является выполнение команды которая позволит нам получит PID процесса и записать его в требуемый pid файл: /var/run/node_exporter.pid Давайте рассмотри содержимое Systemd Service Unit и разберёмся, что же в нём особенное.

[Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network.target

[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/bin/node_exporter
ExecStartPost=+sh -c 'pidof -s node_exporter > /var/run/node_exporter.pid'
Restart=always
PIDFile=/var/run/node_exporter.pid

[Install]
WantedBy=multi-user.target

Итак, разделы [Unit] и [Install] ничего особенного для нас не представляют, однако давайте для лучшего понимания рассмотрим и их в порядке от наименее интересных нам в рамках данной темы к наиболее интересным:

  1. [Unit]
  • Description=Prometheus Node Exporte #Эта директива может использоваться для описания имени и основных функций;
  • Wants=network-online.target #В этой директиве перечислены все юниты, от которых зависит этот юнит (служба или устройство);
  • After=network.target #Юниты, перечисленные в этой директиве, будут запущены до запуска текущего;
  1. [Install]
  • WantedBy=multi-user.target #Определяет на каком загрузочном таргете запускать этот юнит.
  1. [Service]
  • Type=simple # systemd запустит эту службу незамедлительно. Процесс при этом не должен разветвляться (fork).
  • User=prometheus #. Указывает имя пользователя, от которого будет запускаться сервис;
  • ExecStart=/usr/local/bin/node_exporter # Указывает путь к исполняемому файлу;
  • ExecStartPost=+sh -c ‘pidof -s node_exporter > /var/run/node_exporter.pid’ # Набор команд выполняемых сразу после запуска основного процесса. Данная строка нам наиболее интересна и подробнейшим образом мы её рассмотрим ниже;
  • Restart=always # Указывает на то, что служба будет стремиться перезагрузиться в случае ошибок и других непредвиденных обстоятельств;
  • PIDFile=/var/run/node_exporter.pid # Ввиду того, что для типа “Simple” pid-файл не создается автоматически, мы создаем его командой приведённой выше, чтобы systemd мог отслеживать основной процесс;

Разбор полётов

Итак, давайте разбираться в том, что мы имеем в строке:

ExecStartPost=+sh -c 'pidof -s node_exporter > /var/run/node_exporter.pid'
  1. ExecStartPost=- директива которая определяет, какой набор команд будет выполнен сразу после того, как стартует основной сервис.
  2. + - директива, которая повышает привилегии на исполнение команды;
  3. sh -c - указывает на то, что командной оболочке нужно считывать команды из операнда command_string (из строки), вместо стандартного ввода.
  4. 'pidof -s node_exporter > /var/run/node_exporter.pid' - и есть наша командная строка, которая при помощи pidof -s node_exporter считывае PID процесса node_exporter и по средствам перенаправления вывода > отправляет PID в заданный нами файл /var/run/node_exporter.pid

Почему именно так?

Такой подход необходим ввиду того, что файл /var/run/node_exporter.pid имеет права на запись только для владельца, а владельцем его является root, при этом наш пользователь prometheus привилегий суперпользователя не имеет. Казалось бы: мы же указываем директиву + и она повышает уровень привилегий до необходимого… Да именно, так и происходит. Однако уровень привилегий повышается только для части команды, а именно: pidof -s node_exporter, при этом данной команде такой уровень привилегий и не нужен, а нужен он именно для перенаправления в файл > /var/run/node_exporter.pid. Именно для того, чтобы уровень привилегий был повышен для всей цепочки команд, мы и завернули его в строку и отправили в шелл.

0%