С чего начать Первые шаги трек · 15 ступеней
Linux Labs

Таймеры systemd — задачи по расписанию

10 мин Ubuntu 24.04 · systemd 255

Таймер systemd — юнит .timer, который по расписанию запускает одноимённую службу; её вывод пишется в журнал.

Шпаргалка

8 команд Версия для печати
  • systemctl list-timers таймеры и следующий запуск
  • systemctl list-timers --all и неактивные тоже
  • sudo systemctl enable --now clean.timer включить и запустить
  • sudo systemctl start clean.service выполнить задачу сейчас
  • journalctl -u clean.service -n 20 вывод последних запусков
  • systemd-analyze calendar 'Mon..Fri 03:00' проверить расписание
  • systemctl cat clean.timer что записано в юните
  • sudo systemctl daemon-reload после правки файлов юнитов

Обзор

Таймер — юнит systemd с расширением .timer. Сам он ничего не выполняет: в назначенное время он запускает службу, по умолчанию одноимённую (clean.timer → clean.service). Поэтому задача — это пара файлов в /etc/systemd/system: служба описывает, что делать, таймер — когда.

ini
# /etc/systemd/system/clean.service
[Unit]
Description=Cleanup old exports

[Service]
Type=oneshot
ExecStart=/usr/local/bin/clean.sh
ini
# /etc/systemd/system/clean.timer
[Unit]
Description=Run cleanup daily

[Timer]
OnCalendar=*-*-* 03:30
Persistent=true

[Install]
WantedBy=timers.target

Type=oneshot — служба, которая выполняет команду и завершается; пока скрипт работает, она в состоянии activating. Включают таймер: у службы нет секции [Install], и systemctl enable clean.service выдаст только длинное предупреждение. Включённый таймер виден в списке со временем следующего запуска:

text
student@ubuntu:~$ systemctl list-timers clean.timer --no-pager
NEXT                        LEFT LAST PASSED UNIT        ACTIVATES
Wed 2026-10-21 03:30:00 UTC  17h -         - clean.timer clean.service
cron таймер systemd
вывод задачи почта или пропадает журнал службы, journalctl -u
машина была выключена запуск пропущен Persistent=true — выполнит после старта
прошлый запуск ещё идёт стартует второй тот же юнит второй раз не стартует
запустить вне расписания скопировать команду в терминал systemctl start в тех же условиях

Расписание OnCalendar

Полная форма — ДеньНедели Год-Месяц-День Час:Минута:Секунда. Любая часть может быть *, списком через запятую, диапазоном через .. или шагом через /.

Запись Когда
hourly каждый час, в :00
daily каждый день в 00:00
weekly по понедельникам в 00:00
*-*-* 03:30 каждый день в 03:30
Mon..Fri 03:00 по будням в 03:00
Sat,Sun 10:00 по выходным в 10:00
*-*-01 04:00 первого числа каждого месяца
*:0/15 каждые 15 минут
03:00 Europe/Moscow в 03:00 по московскому времени

Без пояса время считается по часам машины (timedatectl). Запись проверяет systemd-analyze calendar — она показывает и ближайший запуск:

text
student@ubuntu:~$ systemd-analyze calendar 'Mon..Fri 03:00'
  Original form: Mon..Fri 03:00
Normalized form: Mon..Fri *-*-* 03:00:00
    Next elapse: Wed 2026-10-21 03:00:00 UTC
       From now: 16h left

Кроме календаря таймер умеет считать от событий: OnBootSec=5min — через пять минут после загрузки, OnUnitActiveSec=1h — через час после прошлого запуска службы.

Окружение службы

Служба стартует вне твоего терминала, и окружение у неё своё:

text
student@ubuntu:~$ sudo systemd-run --pipe --wait --quiet \
    sh -c 'echo "PATH=$PATH"; echo "HOME=$HOME"; pwd; id -un'
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
HOME=
/
root
  • текущий каталог — /: относительный путь в скрипте считается от корня; свой каталог задаёт WorkingDirectory=;
  • PATH короткий: ~/bin и добавки из ~/.bashrc в нём нет;
  • переменных из ~/.bashrc и из строк crontab нет — их задают Environment=ИМЯ=значение или EnvironmentFile=;
  • пользователь — root, HOME пуст; с User=student служба идёт от student и получает HOME=/home/student;
  • ~/.profile и ~/.bashrc не читаются, umask — 0022.

Журнал

Всё, что скрипт печатает в stdout и stderr, попадает в журнал службы. Ключ -o cat убирает из строк время, имя машины и clean.sh[PID]:

text
student@ubuntu:~$ sudo journalctl -u clean.service -o cat
Starting clean.service - Cleanup old exports...
cleanup started
clean.service: Deactivated successfully.
Finished clean.service - Cleanup old exports.

Рецепты

5

Перевести задачу из cron в таймер

  1. Служба: Type=oneshot, в ExecStart= — полный путь к скрипту, нужные переменные — в Environment=.
  2. Таймер с тем же расписанием: 30 3 * * * в cron — это OnCalendar=*-*-* 03:30.
  3. sudo systemctl daemon-reload, затем sudo systemctl start clean.service и журнал — убедись, что задача проходит.
  4. sudo systemctl enable --now clean.timer.
  5. Убери строку из crontab или файл из /etc/cron.d.

Выполнить задачу сейчас и проверить итог

bash
sudo systemctl start clean.service; echo $?
systemctl status clean.service --no-pager
journalctl -u clean.service -n 20 --no-pager

Для oneshot команда systemctl start ждёт конца скрипта и возвращает 0 или 1. В status видно, с каким кодом он вышел: status=0/SUCCESS.

Через час после прошлого запуска

ini
[Timer]
OnBootSec=5min
OnUnitActiveSec=1h

Временный таймер без файлов

bash
sudo systemd-run --on-calendar='*:0/5' --unit=tick /bin/true
text
Running timer as unit: tick.timer
Will run service as unit: tick.service

Такой таймер живёт до перезагрузки, остановить его — systemctl stop tick.timer.

Проверить скрипт в окружении службы

bash
sudo systemd-run --pipe --wait /usr/local/bin/clean.sh
sudo systemd-run --pipe --wait -p User=student /usr/local/bin/clean.sh

Скрипт выполнится временной службой: каталог /, короткий PATH, root или пользователь из -p User=. Ошибки окружения видны до первого запуска по расписанию, а код systemd-run равен коду скрипта:

text
Finished with result: exit-code
Main processes terminated with: code=exited/status=3

Неполадки

8

Руками работает, по таймеру — нет

Дело почти всегда в окружении службы (раздел «Окружение службы» выше). Причину пишет журнал службы:

text
student@ubuntu:~$ sudo journalctl -u clean.service -o cat | tail -3
/usr/local/bin/clean.sh: line 2: report-tool: command not found
clean.service: Deactivated successfully.
Finished clean.service - Cleanup old exports.

command not found — полный путь или Environment=PATH=…; файл «не найден» по относительному пути — WorkingDirectory=; пустая переменная — Environment=.

Job for clean.service failed

Скрипт вернул не 0. В журнале службы:

text
clean.service: Main process exited, code=exited, status=1/FAILURE
clean.service: Failed with result 'exit-code'.

Код скрипта — код его последней команды (см. коды завершения). Служба остаётся в failed до следующего успешного запуска или systemctl reset-failed.

Таймер есть, а задача не запускается

systemctl list-timers --all: прочерк в столбце NEXT значит, что таймер не запущен. systemctl is-enabled clean.timer покажет disabled — выполни sudo systemctl enable --now clean.timer.

Refusing to start, unit … to trigger not loaded

Таймеру не на что указывать: службы с тем же именем нет. Переименуй файлы одинаково или назови службу в таймере: Unit=clean.service в [Timer].

Failed to parse calendar specification

Ошибка в OnCalendar=, таймер не запустится. В журнале (journalctl -u clean.timer) две строки: clean.timer:5: Failed to parse calendar specification, ignoring: daily at 3 и Timer unit lacks value setting. Refusing.

Проверь запись командой systemd-analyze calendar '…', а весь файл — systemd-analyze verify /etc/systemd/system/clean.timer.

Warning: The unit file … changed on disk

Файл юнита поправлен, а systemd работает по старой версии — и старому расписанию. Выполни sudo systemctl daemon-reload, затем sudo systemctl restart clean.timer.

The unit files have no installation config

enable вызван для службы. Включать нужно таймер: sudo systemctl enable --now clean.timer.

Таймер сработал один раз, дальше — тишина

В службе стоит RemainAfterExit=yes. После первого запуска она остаётся активной, хотя скрипт уже завершился:

text
     Active: active (exited) since Tue 2026-10-20 10:36:40 UTC; 46ms ago

Следующий запуск таймера (и systemctl start) ничего не делает: служба уже «работает». Задаче по расписанию эта строка не нужна — убери её, выполни daemon-reload и systemctl stop clean.service.

Опасно

2

Задача и в cron, и в таймере

Перенёс задачу в таймер — убери её из cron. Иначе она идёт по двум расписаниям, и запуски могут наложиться: systemd не знает о копии из cron. Защита от наложения между разными запусками — flock.

Persistent=true после долгого простоя

Время прошлого запуска хранится в /var/lib/systemd/timers/stamp-*.timer. Если машина была выключена, пропущенный запуск случится сразу после загрузки — тяжёлая задача (резервная копия, очистка) стартует вместе с системой.

Термины

2
таймер systemd systemd timer
Юнит .timer, который по расписанию или через заданное время запускает службу, обычно одноимённую. Ещё встречается в: Cron, flock, Bash-скрипты: запуск, переменные, аргументы, chrony: синхронизация времени по NTP и ещё 4
служба oneshot oneshot service
Служба systemd с Type=oneshot: выполняет команду и завершается; systemctl start ждёт её конца и сообщает успех или сбой.

См. также

  • cron — классический планировщик и формат crontab.
  • systemd — юниты и их зависимости.
  • systemctl — запуск, включение и состояние юнитов.
  • journalctl — журнал службы и фильтры по времени.
  • flock — защита от одновременных запусков.
  • exit-codes — почему служба failed и что значит status=1.
  • env-vars — откуда берётся PATH и почему его нет у службы.
  • timedatectl — часовой пояс, по которому считает таймер.
Загрузка…