Таймер или cron: задача выполняется дважды
Классическая ошибка переезда: таймер настроили, а запись в cron забыли убрать. Задача выполняется дважды, и если она не рассчитана на повторный запуск, последствия бывают неприятными.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Осталась запись в cron
Запись могла быть в crontab пользователя, в системном файле или в каталоге периодических задач. Проверять надо все места.
-
Задача не защищена от повторного запуска
Даже без дублирования таймер и ручной запуск могут наложиться. Задача должна это выдерживать.
-
Разные расписания дают неожиданные совпадения
Таймер и cron с похожими, но не одинаковыми расписаниями дают то один запуск, то два.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Активные таймеры.
systemctl list-timers --all --no-pager | headОстатки записей cron.
sudo grep -r myapp /etc/cron* /var/spool/cron 2>/dev/null | headСколько запусков было за сутки.
journalctl -u myapp.service --since "1 day ago" --no-pager | grep -ci startedРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Запись могла быть в crontab пользователя, в системном файле или в каталоге периодических задач. Проверять надо все места.
- Как проверить
-
Посмотрите все источники задач.
crontab -l 2>/dev/null; sudo crontab -l 2>/dev/null sudo ls -l /etc/cron.d/ /etc/cron.daily/ 2>/dev/null
- Как исправить
- Удалите запись cron после переезда на таймер. Оставлять «на время» не стоит: двойные запуски тяжело заметить.
- Почему происходит
- Даже без дублирования таймер и ручной запуск могут наложиться. Задача должна это выдерживать.
- Как проверить
-
Посмотрите, есть ли блокировка внутри задачи.
systemctl cat myapp.service | grep -i ExecStart
- Как исправить
-
Добавьте в задачу блокировку файлом (
flock) либо полагайтесь на systemd: пока служба активна, повторный запуск не создаётся.
- Почему происходит
- Таймер и cron с похожими, но не одинаковыми расписаниями дают то один запуск, то два.
- Как проверить
-
Сравните расписания.
systemctl list-timers --all --no-pager | grep myapp sudo grep -r myapp /etc/cron* 2>/dev/null
- Как исправить
- Оставьте один механизм. Таймеры дают журнал, зависимости и ограничения ресурсов — для важных задач это перевешивает привычность cron.
Пример вывода
Задача выполнилась дважды: таймером и заданием cron. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
$ journalctl -u backup.service --since today --no-pager | grep -c "Started"
2
$ systemctl list-timers --no-pager | grep backup
Tue 2026-09-16 03:00:00 MSK backup.timer backup.service
$ sudo cat /etc/cron.d/backup
0 3 * * * root /usr/local/bin/backup.sh
Связанные ошибки
- Задача cron не выполняется Задача в crontab не запускается: короткий PATH, права на файл задачи, точка в имени файла, отсутствие перевода строки.
- Таймер активен, но не срабатывает Таймер systemd в состоянии active, но служба не запускается. Разбор: нет условия срабатывания, таймер не включён, ошибка в OnCalendar.
- Failed to parse calendar expression: ошибка в OnCalendar systemd не разбирает календарное выражение таймера. Правила записи OnCalendar и проверка через systemd-analyze calendar.
- clocksource: Marking clocksource unstable Ядро переключило источник времени. Службы видят скачки времени, таймеры срабатывают не тогда, когда ожидалось.
- status=212/TIMERSLACK в systemd Код 212/TIMERSLACK: не удалось задать допуск таймеров процесса из TimerSlackNSec=. Редкий код.
- Два таймера на одну службу: срабатывания накладываются Одна служба вызывается несколькими таймерами: запуски накладываются, часть срабатываний теряется.
- Периодическая очистка неиспользуемых блоков не работает Задача очистки блоков падает: файловая система или устройство не поддерживают операцию, либо путь смонтирован не так.
- Пропущенное срабатывание таймера: Persistent и выключенная машина Таймер не выполнил задачу, потому что в момент срабатывания машина была выключена или служба была недоступна. Как работает Persistent=true.
Где встречается чаще всего
Источники
-
systemd.timer(5)
Таймеры как замена cron. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено оставленной записью cron после переезда на таймер.