Налаштування серверів

Cron-задачі на сервері: як автоматизувати рутину і звільнити собі 10 годин на тиждень

Уявіть: кожного ранку о 3:00 хтось невидимий заходить на ваш сервер, чистить старі логи, робить бекап бази даних, перезапускає завислий PHP-процес і тихо йде. Ви спите. Сайт працює. Клієнти задоволені. Це не магія і не дорогий адміністратор на зарплаті - це cron, один з найпотужніших і водночас найбільш недооцінених інструментів на будь-якому Linux-сервері. Але ось парадокс: більшість власників сайтів або взагалі не знають про cron-задачі, або налаштовують їх раз і забувають. А потім дивуються, чому бекапи не робляться, кеш переповнений, а сервер повільнішає з кожним тижнем.

Що таке cron і чому він важливіший за ваш ранковий будильник

Cron - це планувальник задач в Unix-подібних системах. Він існує з 1975 року, і за майже 50 років принцип не змінився: ви кажете серверу "роби ось це, в ось цей час, з ось такою періодичністю". Все. Без графічних інтерфейсів, без drag-and-drop, без підписок за $29/місяць. Просто один рядок тексту - і сервер виконує вашу команду як годинник.

Файл, де зберігаються ці інструкції, називається crontab. Кожен користувач системи має свій crontab, і є окремий системний - для задач від імені root. Синтаксис виглядає як набір цифр зі зірочками, і саме тут більшість людей лякаються і закривають термінал. Даремно.

Формат простий - п'ять полів через пробіл, потім команда:

Поле Значення Діапазон Приклад
Хвилина Коли запускати (хвилина) 0-59 30
Година Коли запускати (година) 0-23 3
День місяця Який день 1-31 15
Місяць Який місяць 1-12 *
День тижня Який день тижня 0-7 1

Зірочка (*) означає "кожен". Тобто 30 3 * * * - це "кожного дня о 3:30 ночі". Бачите? Не складніше за налаштування будильника. Тільки цей будильник не для вас - для сервера.

П'ять задач, які мають бути в crontab кожного сервера

Я бачив сотні серверів, де crontab був абсолютно порожній. Це як купити автомобіль і ніколи не міняти масло - якийсь час їде, а потім раптово помирає. Ось мінімальний набір cron-задач, без якого ваш сервер живе в борг:

  1. Автоматичний бекап бази даних. Щоденно, о 2:00-4:00 ночі. Команда mysqldump для MySQL або pg_dump для PostgreSQL. Без цього ви граєте в рулетку з даними клієнтів.
  2. Ротація та очищення логів. Логи ростуть непомітно, поки не з'їдять весь диск. Щотижневе стиснення та видалення файлів старше 30 днів - це гігієна сервера.
  3. Перевірка вільного місця на диску. Скрипт, який надсилає email-сповіщення, коли залишається менше 10% простору. Один рядок в cron, який рятує від катастрофи.
  4. Оновлення SSL-сертифікатів. Якщо використовуєте Let's Encrypt, certbot має автоматично поновлювати сертифікати. Без cron - забудете, і сайт покаже страшне попередження браузера.
  5. Перезапуск "зомбі"-процесів. PHP-FPM, Node.js, Redis - все це іноді зависає. Проста перевірка раз на 5 хвилин і перезапуск при потребі коштує нуль, а економить години простою.

"Автоматизація - це не про лінь. Це про визнання того, що людський мозок не пристосований виконувати одну й ту ж дію ідеально 365 днів поспіль. Машина - пристосована." - Tom Limoncelli, автор книги "The Practice of System and Network Administration"

Типові помилки, які перетворюють автоматизацію на бомбу сповільненої дії

Cron простий у використанні, але підступний у деталях. Я пам'ятаю випадок, коли клієнт налаштував бекап бази даних кожні 5 хвилин замість кожні 5 годин. Одна зайва зірочка - і сервер генерував 288 дампів на добу по 2 ГБ кожен. Диск закінчився за три дні. У п'ятницю ввечері, звісно.

Ось топ помилок, які я зустрічаю регулярно:

  • Відсутність перенаправлення виводу. Cron надсилає результат виконання на email кореневому користувачу. Якщо email не налаштований, вивід накопичується в мертвій поштовій скриньці і їсть місце.
  • Використання відносних шляхів. Cron не знає ваш робочий каталог. Пишіть /usr/bin/php /var/www/site/cron.php, а не просто php cron.php.
  • Перекриття задач. Якщо скрипт виконується 15 хвилин, а ви запускаєте його кожні 10 - дві копії почнуть конфліктувати. Використовуйте flock для блокування.
  • Забуті задачі. Хтось колись додав тестовий рядок і забув видалити. Через рік ніхто не знає, що це і навіщо, але боїться чіпати.
  • Неправильний часовий пояс. Cron працює в часовій зоні сервера. Якщо сервер у Франкфурті, а ви думаєте за київським часом - ваш "нічний" бекап запуститься в прайм-тайм.

Золоте правило: після додавання будь-якої cron-задачі перевіряйте її вручну. Виконайте команду в терміналі, переконайтеся, що вона працює, і тільки тоді довіряйте автоматизації.

Альтернативи та доповнення: коли cron недостатньо

Cron чудовий для простих повторюваних задач. Але у нього є обмеження. Він не вміє реагувати на події ("запусти бекап, коли навантаження впаде нижче 20%"). Він не має вбудованого моніторингу ("попередь мене, якщо задача не виконалася"). І він не підходить для складних ланцюжків залежностей ("спочатку зроби A, потім B, але тільки якщо A пройшло успішно").

Для таких сценаріїв існують більш просунуті інструменти:

Інструмент Складність Найкраще для Вартість
Cron Низька Прості повторювані задачі Безкоштовно
Systemd timers Середня Задачі з логуванням і залежностями Безкоштовно
Ansible + cron Середня Керування cron на багатьох серверах Безкоштовно
Healthchecks.io Низька Моніторинг виконання cron-задач Від $0
Apache Airflow Висока Складні пайплайни обробки даних Безкоштовно

Але для 90% хостинг-серверів стандартного cron з додатковим моніторингом через Healthchecks.io або аналоги - більш ніж достатньо. Ідея проста: cron-задача після виконання "пінгує" зовнішній URL. Якщо пінг не прийшов - сервіс надсилає вам сповіщення. Елегантно і майже безкоштовно.

Практичний шаблон: налаштовуємо crontab за 15 хвилин

Досить теорії. Відкривайте термінал і вводьте crontab -e. Ось готовий шаблон, який я використовую як стартову точку для нових серверів:

# Бекап MySQL щодня о 3:00
0 3 * * * /usr/bin/mysqldump -u root mydb | gzip > /backups/db_$(date +%F).sql.gz 2>&1 | logger -t cron-backup

# Видалення бекапів старше 14 днів
30 3 * * * /usr/bin/find /backups/ -name "*.sql.gz" -mtime +14 -delete

# Перезапуск PHP-FPM щонеділі о 4:00
0 4 * * 0 /usr/bin/systemctl restart php8.2-fpm

# Оновлення SSL кожні 12 годин
0 */12 * * * /usr/bin/certbot renew --quiet

# Перевірка диску кожну годину
0 * * * * /scripts/check_disk.sh

Зверніть увагу на кілька речей. Всі шляхи - абсолютні. Час розподілено так, щоб задачі не запускалися одночасно. Бекапи чистяться автоматично. SSL оновлюється з запасом (сертифікат дійсний 90 днів, а перевірка йде двічі на добу).

Для перевірки того, що ваш crontab коректний, використовуйте онлайн-валідатор crontab.guru. Вставляєте свій вираз часу - отримуєте людиночитабельне пояснення. Це як Google Translate, тільки для cron-синтаксису.

Безпека cron-задач: те, про що мовчать туторіали

Ось що рідко згадують у статтях про cron: кожна cron-задача - це потенційна вразливість. Якщо зловмисник отримає доступ до вашого crontab, він може додати задачу, яка запускатиметься з правами вашого користувача. А якщо це root-crontab - з правами суперкористувача.

Базові правила безпеки:

  • Ніколи не зберігайте паролі напряму в crontab. Використовуйте файли конфігурації з обмеженими правами (chmod 600) або змінні оточення.
  • Обмежте, хто може використовувати cron, через файли /etc/cron.allow та /etc/cron.deny.
  • Регулярно переглядайте crontab всіх користувачів: for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null; done
  • Логуйте виконання задач - стандартний syslog записує запуски, але не результати. Додавайте власне логування.

Один мій знайомий адміністратор виявив у crontab забутого тестового користувача скрипт, який щогодини завантажував файл з невідомого URL. Скрипт був там понад рік. Ніхто не перевіряв. Це як знайти чужі ключі від вашої квартири на дверному килимку - неприємний сюрприз.

Налаштування cron - це не разова задача. Це живий організм, який потребує уваги хоча б раз на місяць. Перегляньте свій crontab прямо зараз. Серйозно - відкрийте термінал і введіть crontab -l. Що ви там побачите? Порожнечу, хаос чи чітку систему? Відповідь на це питання скаже більше про стан вашого сервера, ніж будь-який моніторинг.