Как отправить электронное письмо, если перезапущен сервис systemd?

8

У меня есть критическое приложение, которое запускается как служба systemd.

Он настроен на перезагрузку при возникновении сбоя.

Как отправить электронное письмо, если приложение перезапустится?

Greg
источник
2
Я не знаю, как это сделать с помощью systemd, но с помощью monit вы можете заставить его наблюдать за процессом и отправлять уведомление в случае изменения идентификатора процесса.
Зоредаче

Ответы:

16

Для начала вам понадобятся два файла: исполняемый файл для отправки почты и .service для запуска исполняемого файла. В этом примере исполняемый файл - это просто скрипт оболочки, использующий sendmail:

/usr/local/bin/systemd-email:

#!/bin/bash

/usr/bin/sendmail -t <<ERRMAIL
To: $1
From: systemd <root@$HOSTNAME>
Subject: $2
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset=UTF-8

$(systemctl status --full "$2")
ERRMAIL

Какой бы исполняемый файл вы не использовали, он, вероятно, должен принимать как минимум два аргумента, как это делает скрипт оболочки: адрес для отправки и файл модуля для получения статуса. .serviceМы создаем передадим эти аргументы:

/etc/systemd/system/status-email-user@.service:

[Unit]
Description=status email for %i to user

[Service]
Type=oneshot
ExecStart=/usr/local/bin/systemd-email address %i
User=nobody
Group=systemd-journal

Где пользователь - это адрес электронной почты, а адрес - адрес электронной почты этого пользователя. Несмотря на то, что получатель жестко запрограммирован, файл модуля, для которого передается отчет, передается в качестве параметра экземпляра, поэтому эта одна служба может отправлять электронную почту для многих других модулей. На этом этапе вы можете начать status-email-user@dbus.serviceпроверять, можете ли вы получать электронные письма.

Затем просто отредактируйте сервис, для которого вы хотите получать электронные письма, и добавьте OnFailure=status-email-user@%n.serviceего в [Unit]раздел. %nпередает имя устройства в шаблон.

Источник: archlinux wiki: системные таймеры MAILTO

gf_
источник
Но @Dave не требует другого сервиса. Он хочет, чтобы служба, которую он уже использует, могла отправлять почту при каждом запуске / перезапуске. Для этого есть опция ExecStartPost.
Ярослав Кучера
@JaroslavKucera Я думаю, что это решать до ОП ... :) Кроме того, я не уверен, что ExecStartPostэто правильный выбор: он также будет срабатывать после "нормального" запуска, не только в случае сбоя, верно ?
gf_
Мне интересно, почему за это проголосовали - пожалуйста, поднимите свои голоса и говорите!
gf_
Потому что вопрос не в другом сервисе, а в модификации существующего сервиса. Да, ExecStartPost будет инициировать отправку почты даже при обычном запуске. Я не знаю ничего, что будет работать только при перезагрузке.
Ярослав Кучера
@JaroslavKucera Ну, кажется, ОП не согласен, но, конечно, придерживайтесь своего мнения.
gf_
2

Решение, предложенное @gf_, хорошо сработало для нашей ситуации при использовании clickhouse на CentOS7. Clickhouse несколько регулярно падает на нас, поэтому нам нужно было как перезапустить его автоматически, так и получать уведомления о перезапуске. Хотя добавление второго сервиса в systemd кажется немного неуклюжим, это необходимо из-за дизайна systemd.

При этом это решение в сочетании с автоматическим перезапуском перестало работать для нас, когда мы развернули CentOS8. Это связано с тем, что systemd v239, поставляемый в C8, внес изменение в OnFailure=семантику в сочетании с нестандартной конфигурацией Restart=( Restart=on-failureв нашем случае). Новое OnFailure=поведение запускает однократную службу только в случае полной перезагрузки, а не только после сбоя. Это более новое поведение с радостью перезапустило бы службу, но мы не получили бы электронное письмо, поскольку OnFailure=больше не вызывалось.

Обратите внимание на наше основное ожидание: мы хотели, чтобы systemd перезапустил процесс и отправил уведомление по электронной почте. В результате обновления v239 наше предыдущее решение, на которое ссылается gf_, больше не работает. К счастью, мы смогли заставить это работать.

Наше решение - использовать ExecStopPostдля вызова скрипта уведомления по электронной почте. Это работает нормально, но теперь возникла новая проблема: уведомление по электронной почте было отправлено, когда служба clickhouse запускается нормально, например, при запуске сервера. Хотя это и не имеет большого значения, в идеале мы хотели получать уведомления по электронной почте только о сбоях. Мы смогли добиться этого, добавив следующий код в наш почтовый скрипт:

# Don't do anything if the service intentionally stopped successfully. if [ $SERVICE_RESULT == "success" ]; then exit fi

... $SERVICE_RESULTэто переменная окружения, предоставляемая systemd целевому процессу ExecStopPost. Проверяя successрезультат, мы предполагаем, что этот вызов произошел при обычном запуске или завершении работы, и ничего не делаем. При любом другом значении, например signal, скрипт продолжит отправку электронного письма. Возможные значения этой переменной указаны в документации .

Спасибо gf_ за первоначальное решение. Я надеюсь, что люди найдут мое обновление полезным для CentOS8. Еще несколько ссылок, которые помогли мне:

  1. /superuser/1360346/how-to-send-an-email-alert-when-a-linux-service-has-stopped
  2. /unix/422933/confusing-systemd-behaviour-with-onfailure-and-restart
  3. /unix/197636/run-an-arbitrary-command-when-a-service-fails
Энтони Нгуен
источник
0

Вы можете попытаться использовать системную опцию сервиса ExecStartPost.

Описание доступно здесь:

https://www.freedesktop.org/software/systemd/man/systemd.service.html

В файле определения сервиса может быть больше объявлений этой опции. Это срабатывает один за другим.

У вас также будет несколько примеров в вашей системе.

Ярослав Кучера
источник
-1

Вы можете создать сценарий оболочки для проверки состояния службы и отправки электронной почты во время загрузки сервера. Эта ссылка может помочь вам

/ubuntu/814/how-to-run-scripts-on-start-up

billcyz
источник
1
Этот вопрос не о загрузке, а о перезапуске службы, который может произойти через некоторое время после загрузки. Следовательно, я не уверен, если ваш ответ какой-либо помощи.
gf_