Skip to content
VDS · Застосунки та боти

Заплановані завдання: cron і таймери systemd

Як запускати завдання за розкладом, чому завдання працює вручну, але мовчить у cron, і коли переходити на таймери systemd.

Оновлено 23 серпня 2026 р.

Резервні копії, поновлення сертифікатів, очищення тимчасових файлів, нічні звіти — усе це заплановані завдання. На Linux їх розв'язують двома способами: класичний cron і таймери systemd.

Cron: швидкий старт

Розклад користувача редагується так:

crontab -e
crontab -l

Формат рядка — п'ять полів і команда:

# min  hour  day  month  day-of-week  command
  0    4    *     *      *            /usr/local/bin/backup.sh
  */15 *    *     *      *            /usr/local/bin/check.sh
  30   3    *     *      0            /usr/bin/systemctl restart myapp

Корисні скорочення: @daily, @hourly, @reboot. Щоб перевірити, чи завдання взагалі запускалися:

grep CRON /var/log/syslog | tail -30
journalctl -u cron --since "1 hour ago"

Чому скрипт працює вручну, але не в cron

Це найпоширеніша проблема, і причина майже завжди одна з трьох.

Інше середовище. У cron мінімальний PATH і жодної з ваших змінних із .bashrc. Використовуйте повні шляхи до програм і задавайте змінні явно на початку скрипта або в crontab:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Інший каталог. Завдання стартує в домашньому каталозі користувача, тож відносні шляхи вказують в інше місце. Завжди використовуйте абсолютні шляхи.

Вивід нікуди не йде. Помилка була, але її ніхто не побачив. Записуйте лог:

0 4 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Ще дві дрібниці: символ % у рядку cron потрібно екранувати як \%, а файл crontab має закінчуватися символом нового рядка — інакше останнє завдання буде проігноровано.

Потрібно переконатися ззовні, що завдання виконалося. Мовчазний cron виглядає точно так само, як успішний. Налаштуйте push-перевірку в Uptime Kuma: скрипт надсилає запит на адресу в кінці, і якщо запиту не було добу, ви отримаєте сповіщення.

Таймери systemd

Коли завдання складніше за одну команду, зручніше використовувати таймер: у нього є журнал, залежності, обмеження ресурсів і захист від запуску двох копій одночасно.

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run nightly backup

[Timer]
OnCalendar=*-*-* 04:00:00
Persistent=true
RandomizedDelaySec=15m

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers
journalctl -u backup.service -n 50

Persistent=true надолужує пропущений запуск, якщо машина була вимкнена — cron так не вміє. RandomizedDelaySec розподіляє навантаження, щоб десяток завдань не стартували в одну секунду.

Що варто врахувати

  • Час машини за замовчуванням — UTC. Перевірте timedatectl, перш ніж ставити «4 ранку».
  • Важкі завдання (архіви, перевірка резервних копій) залежать від швидкості диска. Дивіться швидкість диска і плануйте їх на ніч.
  • Довге завдання, що запускається щоп'ять хвилин, накладатиметься саме на себе. У systemd допомагає Type=oneshot; у cron використовуйте блокування через flock:
*/5 * * * * /usr/bin/flock -n /tmp/job.lock /usr/local/bin/job.sh