Одноразовая задача: как не получить ложный сбой
Одноразовые задачи ведут себя иначе, чем постоянные службы: они завершаются, и это нормально. Ошибки возникают на стыке — когда от такой задачи ждут поведения службы или наоборот.
Что это значит
Правило простое: Type=oneshot для задач, которые отрабатывают и завершаются. Если состояние «выполнено» должно сохраняться, добавьте RemainAfterExit=yes. Если задачу вызывает таймер или наблюдатель — этот параметр, наоборот, помешает повторным запускам.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Мониторинг считает завершение сбоем
Проверка «служба active» для одноразовой задачи всегда провалится, если не задано сохранение состояния.
-
Задача по таймеру не запускается повторно
С сохранением состояния задача остаётся активной, и следующее срабатывание таймера ничего не делает.
-
Последовательность шагов в одной задаче
При
Type=oneshotдопустимо несколько команд запуска, и они выполняются по порядку. Неудача любой останавливает остальные.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Тип, поведение после завершения и код последнего запуска.
systemctl show myapp.service -p Type -p RemainAfterExit -p ExecMainStatusПравильная проверка для одноразовых задач.
systemctl is-failed myapp.serviceРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Проверка «служба active» для одноразовой задачи всегда провалится, если не задано сохранение состояния.
- Как проверить
-
Посмотрите тип и параметр.
systemctl show myapp.service -p Type -p RemainAfterExit -p SubState
- Как исправить
-
Добавьте
RemainAfterExit=yesи проверяйте черезsystemctl is-failed, а не черезis-active.
- Почему происходит
- С сохранением состояния задача остаётся активной, и следующее срабатывание таймера ничего не делает.
- Как проверить
-
Посмотрите параметр и историю запусков.
systemctl show myapp.service -p RemainAfterExit systemctl list-timers myapp.timer --no-pager
- Как исправить
- Уберите сохранение состояния у задач, вызываемых таймером: они должны завершаться.
- Почему происходит
- При
Type=oneshotдопустимо несколько команд запуска, и они выполняются по порядку. Неудача любой останавливает остальные.
- Как проверить
-
Посмотрите список команд.
systemctl cat myapp.service | grep -c "^ExecStart="
- Как исправить
- Для шагов, неудача которых допустима, ставьте дефис перед командой. Это точнее, чем прятать ошибки внутри скрипта.
Пример вывода
Задача выполнена, состояние честно это отражает. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
● migrate.service - Применение миграций
Loaded: loaded (/etc/systemd/system/migrate.service; enabled)
Active: active (exited) since Mon 2026-09-15 08:00:02 MSK; 6h ago
Process: 1200 ExecStart=/usr/local/bin/migrate (code=exited, status=0/SUCCESS)
Связанные ошибки
- status=0/SUCCESS, но служба считается упавшей Программа завершилась успешно, а systemctl показывает inactive или failed. Разбор: Type=simple против forking, RemainAfterExit, демонизация.
- Таймер активен, но не срабатывает Таймер systemd в состоянии active, но служба не запускается. Разбор: нет условия срабатывания, таймер не включён, ошибка в OnCalendar.
- Служба active, но не работает: обёртки и oneshot Почему состояние active не означает работающую программу: oneshot с RemainAfterExit, обёртки, потерянный главный процесс.
- Apache: Invalid command — не включён модуль Apache не запускается: директива требует модуль, который не подключён. Как найти нужный модуль и включить.
- Apache: правила .htaccess не действуют Файл .htaccess игнорируется: запрещён параметром AllowOverride, нет нужного модуля, файл не читается.
- Configuration file is marked executable Предупреждение о правах: unit-файл помечен исполняемым. Откуда берётся и почему это стоит исправить.
- Configuration file is marked world-inaccessible Предупреждение о правах на unit-файл: служба работает, но файл недоступен для чтения другим.
- Docker: unable to configure the Docker daemon with file daemon.json Демон Docker не запускается из-за ошибки в /etc/docker/daemon.json: неверный JSON или неизвестный ключ.
Источники
-
systemd.service(5)
Type=oneshot, RemainAfterExit= и несколько команд запуска. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Проверено на задаче по таймеру: с сохранением состояния повторные запуски не выполняются.