До основного вмісту

Cron на Linux: налаштування планувальника завдань на VPS

VDS / VPS · 19.04.2026 · 5 хв читання
Ілюстрація до статті «Cron на Linux: налаштування планувальника завдань на VPS»

Cron — демон планування завдань в Unix-системах, що запускає команди за розкладом. Використовується для резервного копіювання, надсилання звітів, оновлення сертифікатів SSL та будь-якої автоматизації.

Синтаксис cron-запису

# ┌───────────── хвилини (0-59)
# │ ┌─────────── години (0-23)
# │ │ ┌───────── день місяця (1-31)
# │ │ │ ┌─────── місяць (1-12)
# │ │ │ │ ┌───── день тижня (0=Sun, 6=Sat)
# │ │ │ │ │
# * * * * * команда

Приклади розкладів

ВиразКоли виконується
* * * * *Щохвилини
0 * * * *Щогодини (о 00 хвилин)
0 3 * * *Щодня о 03:00
0 3 * * 1Щопонеділка о 03:00
0 0 1 * *Перше число кожного місяця
*/15 * * * *Кожні 15 хвилин
0 2,14 * * *О 02:00 та 14:00
@rebootПри кожному перезавантаженні
@dailyРаз на добу (= 0 0 * * *)

Керування crontab

># Редагувати crontab поточного користувача
crontab -e

# Переглянути поточний crontab
crontab -l

# Видалити crontab
crontab -r

# Crontab для іншого користувача (root)
sudo crontab -u www-data -e

Практичні приклади

># Бекап бази даних кожні 6 годин
0 */6 * * * mysqldump -u root -pPASSWORD mydb > /backup/db_$(date +%Y%m%d_%H%M).sql

# Оновлення сертифікатів Let's Encrypt
0 3 * * * certbot renew --quiet

# Очищення логів старіших за 30 днів
0 4 * * * find /var/log/myapp -name "*.log" -mtime +30 -delete

# Запуск Python-скрипта та логування виводу
*/30 * * * * /usr/bin/python3 /opt/scripts/sync.py >> /var/log/sync.log 2>&1

# Перезапуск сервісу о 05:00 щонеділі
0 5 * * 0 systemctl restart myapp

Змінні оточення в cron

># Cron має мінімальне оточення — $PATH може не містити потрібні шляхи
# Завжди використовуйте повні шляхи до команд
/usr/bin/php, /usr/local/bin/wp тощо

# Або явно задайте PATH на початку crontab:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=admin@example.com  # надсилати помилки на email
💡 Налагодження cron: Додайте 2>&1 >> /tmp/cron_debug.log до команди, щоб захопити весь вивід. Якщо cron мовчить при явній помилці — найімовірніше проблема з PATH або правами файлу.

Синтаксис crontab

# Формат: MIN HOUR DOM MON DOW COMMAND
# MIN    = 0-59
# HOUR   = 0-23
# DOM    = 1-31 (день місяця)
# MON    = 1-12
# DOW    = 0-7  (день тижня, 0 і 7 = неділя)

# Кожні 5 хвилин
*/5 * * * * /usr/local/bin/check.sh

# Щодня о 3:30
30 3 * * * /usr/local/bin/backup.sh

# Щопонеділка о 2:00
0 2 * * 1 /usr/local/bin/weekly-report.sh

# Перше число кожного місяця опівночі
0 0 1 * * /usr/local/bin/monthly-cleanup.sh

Логування cron-завдань

# Перенаправлення виводу в лог
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# Придушення виводу (без логів)
0 3 * * * /usr/local/bin/backup.sh > /dev/null 2>&1

Спеціальні значення

ЗначенняЕквівалент
@rebootПри запуску системи
@daily0 0 * * *
@weekly0 0 * * 0
@monthly0 0 1 * *
💡 Для критичних завдань використовуйте systemd timers — вони мають вбудований механізм retry та інтеграцію з journald для логів.

Часті помилки в cron-завданнях

Більшість «cron не працює» насправді означає, що cron відпрацював правильно — просто з несподіваним для автора скрипту оточенням.

/bin/sh: 1: wp: not found

Cron запускає команди з мінімальним PATH, який часто не включає директорію, де лежить потрібна утиліта (наприклад, /usr/local/bin для WP-CLI). Використовуйте повний шлях до бінарника: дізнатися його можна командою which wp у звичайній оболонці і підставити результат у crontab.

You (deploy) are not allowed to use this program (crontab)

Користувач не входить до списку /etc/cron.allow, при цьому сам файл існує — якщо cron.allow присутній, доступ до crontab отримують лише перелічені в ньому користувачі, решта блокуються незалежно від прав sudo. Додайте ім'я користувача до файлу або використовуйте sudo crontab -u username -e від адміністратора.

flock: 456: Resource temporarily unavailable

Це не збій, а захист від повторного запуску: попередній екземпляр завдання ще не завершився і тримає файл блокування, тому новий запуск одразу виходить. Якщо це трапляється регулярно — проблема в тому, що завдання виконується довше за інтервал розкладу, а не в самому блокуванні; з'ясовуйте, чому попередній запуск не вкладається у строк, а не прибирайте flock.

cron чи systemd timer: порівняння

Параметрcronsystemd timer
ЛогуванняВручну у файлВбудоване в journald
Повтор при збоїНемаєЄ (Restart=, OnFailure=)
Точність розкладуДо хвилиниДо секунди
Залежності від інших службНемаєЄ (After=, Requires=)

Для простих періодичних завдань cron лишається простішим у налаштуванні. Для завдань із залежностями від інших служб або потребою автоповтору при збої — див. створення systemd unit-файлу.

Коли cron не підходить

Мінімальний інтервал cron — одна хвилина; для завдань, які мають виконуватися раз на кілька секунд, потрібен окремий демон або systemd timer з OnUnitActiveSec=. Сам по собі cron не захищає від паралельного запуску одного й того самого завдання — якщо попередній екземпляр ще виконується, а новий стартує за розкладом, вони працюватимуть одночасно, конкуруючи за ті самі ресурси, якщо явно не обгорнути команду в flock, як у прикладі вище. Для завдань, критичних до доставлення результату (наприклад, обов'язкове надсилання звіту), cron не дає вбудованого механізму повторних спроб — при збої завдання просто не виконається до наступного запуску за розкладом.

Як перевірити результат

Поява завдання в розкладі ще не означає, що воно реально відпрацювало — перевіряйте факт виконання окремо:

# Переконатися, що cron взагалі запускав завдання
grep CRON /var/log/syslog | grep "backup.sh" | tail -5

# Перевірити код завершення останнього запуску
echo $?

# У системах з journald
journalctl -u cron --since "1 hour ago" | grep backup

Сама поява запису в логі означає лише те, що cron запустив команду — не те, що вона завершилася успішно. Явно логуйте код повернення всередині самого скрипту або додайте MAILTO в crontab, щоб отримувати листа при ненульовому коді завершення.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці