Программа завершилась штатно с кодом 2: SuccessExitStatus в systemd
Утилита проверяет наличие новых файлов. Когда они найдены, она обрабатывает их и возвращает ноль. Когда новых файлов нет, по её документации возвращает два. Для этой утилиты второй результат штатный, но oneshot-служба становится failed. Из-за этого мониторинг сообщает о поломке регулярного задания, хотя работа выполнена согласно контракту программы.
Здесь важно начать с документации самой команды. Код два у другой программы может означать неправильные аргументы или синтаксическую ошибку. Универсального правила «два — это нормально» не существует. Менеджер служб знает базовую договорённость о нуле; дополнительные успешные коды нужно сообщить ему явно и только для конкретного процесса.
Описать значение результата
Для службы с такой утилитой настройка может выглядеть следующим образом. Путь к команде и значение статуса нужно заменить на реальные данные своей программы.
[Service]
Type=oneshot
ExecStart=/opt/import/bin/check-and-import
SuccessExitStatus=2
После этого код два основного процесса рассматривается как успешное завершение. При этом программа продолжает возвращать свой исходный код: systemd меняет классификацию результата, а не переписывает поведение утилиты. Это полезно для диагностики: в статусе можно увидеть, каким именно исходом закончилась последняя попытка.
Альтернатива — wrapper, который переводит документированный «ничего делать не нужно» в ноль, а остальные коды передаёт без изменения. Такой файл удобен, когда команду запускают ещё и вне systemd. Но конструкция command || true слишком груба: она одинаково скроет отсутствие новых файлов, отказ доступа и ошибку подключения. В ней теряется причина завершения, ради которой код возврата вообще существует.
Проверить не только успешный случай
На отдельном тестовом задании воспроизведите три исхода: обычную обработку, отсутствие входных данных и настоящую ошибку. Для каждого посмотрите systemctl show import.service -p Result -p ExecMainStatus и соответствующий участок журнала. Ожидаемая картина: первые два исхода не переводят unit в failed, а третий остаётся ошибкой. Проверка только кода два легко пропускает слишком широкое подавление ошибок в wrapper.
У oneshot-службы успешное выполнение без RemainAfterExit обычно заканчивается не постоянным active, а возвращением в неактивное состояние. Поэтому сама надпись inactive не означает неуспешный импорт. Ориентируйтесь на результат последнего запуска и данные, которые он должен был создать.
Если службу запускает timer, не меняйте вместе с ней расписание: сначала исправьте классификацию результата. В runbook стоит записать смысл каждого допустимого ненулевого кода и ссылку на контракт команды. Тогда следующий инженер поймёт, почему исключение здесь оправдано, и не перенесёт его механически на соседнее задание.
Продолжить практику
За одной настройкой unit обычно стоит весь путь сопровождения приложения: отдельный пользователь, права на данные, сеть, журналы и повторяемые операции. В программе курса «Linux и Bash для DevOps-инженеров» эти задачи собраны вокруг учебного сервера с приложением под systemd. В практике предусмотрены Bash-скрипты проверки состояния и резервного копирования, а также runbook для воспроизводимых поломок. Это подходящее продолжение, если хочется связать отдельные команды в понятный порядок диагностики.
Источник: официальная документация.
Другие задачи по теме: Запуск и жизненный цикл служб systemd.
Продолжить на практике
- Linux и Bash для DevOps-инженеров ↗
Linux для работы с серверами: процессы, права, systemd, сеть, диски и логи. Автоматизируйте повседневные задачи на Bash и разберите типичные сбои сервиса — от занятого порта до переполненного диска.
