Заплановані завдання: 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