Top.Mail.Ru
OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

Cron и фоновые задачи: crontab на хостинге и systemd‑таймеры на VDS, логирование и алерты

Разбираем устойчивые схемы запуска фоновых задач: cron и crontab на виртуальном хостинге, systemd timers на VDS. Готовые шаблоны для wp-cron, queue workers, алертов по почте, логов и ротации, защита от дублей и отладка.
Cron и фоновые задачи: crontab на хостинге и systemd‑таймеры на VDS, логирование и алерты

Фоновые задачи на проекте — это бэкапы, рассылки, очистка кэша, регенерация картинок, сбор метрик, обработчики очередей (queue workers) и многое другое. На виртуальном хостинге этим чаще управляют через cron и crontab, а на VDS — через связку systemd‑unit + systemd‑timer. Важно не просто «что-то запустить раз в час», а обеспечить надёжный график, логи и email alerts, чтобы поломки не оставались незамеченными. Про удалённые резервные копии см. отдельный разбор: S3‑бэкапы с restic/borg.

Cron на виртуальном хостинге: crontab, окружение и логи

На виртуальном хостинге cron обычно доступен пользователю через crontab -e. В нём задаём расписание, переменные окружения и команды. Минимальный набор — явно определить SHELL и PATH, а также MAILTO для уведомлений.

# /var/spool/cron/username (редактируется через crontab -e)
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@site.tld

# Каждые 5 минут: запуск планировщика фреймворка
*/5 * * * * /usr/bin/php /home/username/site/artisan schedule:run >> /home/username/logs/schedule.log 2>&1

# Ночной бэкап с пониженным приоритетом
22 3 * * * ionice -c2 -n7 nice -n 10 /home/username/bin/backup.sh >> /home/username/logs/backup.log 2>&1

Ключевые моменты:

  • Используйте абсолютные пути к бинарям и скриптам (никаких относительных ./script.sh).
  • Задачи, которые пишут в stdout/stderr, отправятся на почту, если задан MAILTO. Если почта недоступна, перенаправляйте вывод в файл: >> file.log 2>&1.
  • Если окружение в cron отличается от интерактивной сессии, добавьте PATH и нужные export в начале crontab или внутри скрипта.

Анти-дубли: защита от параллельных запусков

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

* * * * * flock -n /tmp/wp-cron.lock -c '/usr/bin/php /home/username/public_html/wp-cron.php' >> /home/username/logs/wp-cron.log 2>&1

Это гарантирует, что одновременно будет работать только один экземпляр.

Логирование на хостинге: файлы и ротация

Если у вас нет доступа к logrotate, создайте каталог ~/logs и пишите туда. Ротацию можно сделать отдельным cron‑заданием, оставляя, скажем, 14 дней логов:

15 4 * * * find /home/username/logs -type f -name '*.log' -mtime +14 -delete

Для разбора проблем используйте согласованный формат сообщений: добавляйте метки времени внутри скриптов, логируйте начало/конец, количество обработанных элементов и коды возврата.

Email alerts на cron

Варианты уведомлений:

  • MAILTO — базовый способ: любой вывод скрипта уйдёт письмом.
  • Избирательная отправка при ошибке: cmd || echo "cmd failed on $(hostname)" | mail -s 'Cron error' admin@site.tld.
  • Явные коды возврата: убедитесь, что ваши скрипты завершаются с exit 1 при ошибке, а не молчат.

Если локальная почта недоступна, логируйте в файл и читайте хвост логов при отладке. Продвинутый вариант — отправка в мониторинг из скрипта (CLI‑клиенты или API).

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

systemd timers на VDS: точность, контроль и наблюдаемость

На VDS systemd‑таймеры чаще всего комфортнее cron: выше точность расписания, встроенная устойчивость к рестартам (Persistent=true), логирование через journald, OnFailure‑хуки, перезапуски сервисов, ограничения ресурсов и sandboxing. Если под фоновые задачи нужен отдельный сервер — посмотрите гайд по выбору: как подобрать VDS по CPU/RAM.

Базовый шаблон: .service + .timer

Создаём сервис единичного запуска:

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

[Service]
Type=oneshot
User=www-data
Group=www-data
WorkingDirectory=/var/www/example
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
ExecStart=/usr/local/bin/backup.sh
SyslogIdentifier=site-backup
StandardOutput=append:/var/log/site-backup.log
StandardError=append:/var/log/site-backup.log

Таймер с ежедневным расписанием и защитой от пропусков:

# /etc/systemd/system/site-backup.timer
[Unit]
Description=Run site backup at 03:30 daily

[Timer]  03:30:00
Persistent=true
RandomizedDelaySec=5m
AccuracySec=1m
Unit=site-backup.service

[Install]
WantedBy=timers.target

Активация:

systemctl daemon-reload
systemctl enable --now site-backup.timer
systemctl list-timers --all

Логи с journald и в файлы

По умолчанию вывод сервиса идёт в journald. Для разбора:

journalctl -u site-backup.service --since today
journalctl -u site-backup.service -f

Если нужно — параллельно пишем в файл: StandardOutput=append:/var/log/site-backup.log, StandardError=append:/var/log/site-backup.log. Ротацию файлов оформите в /etc/logrotate.d/site-backup.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Алерты отказов: OnFailure и перезапуски

Хук OnFailure позволяет дернуть другой unit при неуспехе:

# В site-backup.service
[Unit] 

Шаблон уведомителя:

# /etc/systemd/system/notify-admin@.service
[Unit]
Description=Notify admin about failure of %i

[Service]
Type=oneshot
User=root
ExecStart=/usr/bin/mail -s "Unit %i failed on %H" admin@site.tld

Для длительно работающих задач добавьте устойчивость и лимиты перезапусков:

[Unit]
StartLimitBurst=5
StartLimitIntervalSec=300

[Service]
Restart=on-failure
RestartSec=5s

Расписания OnCalendar и тонкая настройка

  • OnCalendar=Mon..Fri 09:00 — по будням в 9:00.
  • OnCalendar=*:0/15 — каждые 15 минут.
  • OnCalendar=monthly — начало месяца.
  • RandomizedDelaySec= — размажьте старт, чтобы не ловить «пиковый час».
  • Persistent=true — если сервер был выключен в момент запуска, задача стартует при ближайшей возможности.

User timers: без root и изолированно

Можно запускать таймеры от конкретного пользователя, не трогая систему:

systemctl --user enable --now my-task.timer
systemctl --user list-timers
journalctl --user -u my-task.service -f

Unit‑файлы кладём в ~/.config/systemd/user/. Удобно для проектных окружений и CI‑агентов.

Шаблон systemd: unit и timer для периодических задач

Длинные процессы и queue workers: nohup, cron и systemd

Обработчики очередей (queue workers) должны работать постоянно и перезапускаться при сбоях. На VDS это проще всего делать через systemd‑сервис с Restart=always и ограничениями ресурсов. На виртуальном хостинге иногда помогает nohup как временная мера.

VDS: systemd‑сервис для очередей

# /etc/systemd/system/app-queue.service
[Unit]
Description=Application queue worker
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/app
Environment="APP_ENV=prod"
ExecStart=/usr/bin/php artisan queue:work --sleep=3 --tries=3 --memory=256
Restart=always
RestartSec=5
# Лимиты и приоритеты
Nice=5
IOSchedulingClass=best-effort
IOSchedulingPriority=7
CPUQuota=50%
MemoryMax=512M
StandardOutput=append:/var/log/app-queue.log
StandardError=append:/var/log/app-queue.log

[Install]
WantedBy=multi-user.target

Далее: systemctl enable --now app-queue, затем journalctl -u app-queue -f. Такой подход надёжнее чем nohup, поскольку systemd контролирует процесс, перезапускает и пишет логи.

Виртуальный хостинг: временный запуск через nohup

Если нет systemd, можно стартовать воркер фоном и «отвязать» от текущего TTY:

nohup /usr/bin/php /home/username/site/artisan queue:work --sleep=3 --tries=3 >> /home/username/logs/queue.log 2>&1 & disown

Чтобы воркер не копился в нескольких экземплярах, используйте flock или pid‑lock внутри скрипта. Также добавьте «сторожок» в crontab, который проверяет жив ли процесс и поднимает его при падении.

wp-cron: перевод на реальный cron или systemd timers

Стандартный wp-cron запускается посетителями сайта и может «спать» на низкой посещаемости. Лучше отключить псевдо‑cron и запускать планировщик по расписанию.

Отключение wp-cron в WordPress

// wp-config.php
define('DISABLE_WP_CRON', true);

Запуск из crontab

*/5 * * * * /usr/bin/php /home/username/public_html/wp-cron.php --doing-cron >> /home/username/logs/wp-cron.log 2>&1

Запуск через systemd timer

# /etc/systemd/system/wp-cron.service
[Unit]
Description=Run WordPress cron

[Service]
Type=oneshot
User=www-data
WorkingDirectory=/var/www/site
ExecStart=/usr/bin/php wp-cron.php --doing-cron
StandardOutput=append:/var/log/wp-cron.log
StandardError=append:/var/log/wp-cron.log

# /etc/systemd/system/wp-cron.timer
[Unit]
Description=Every 5 minutes WordPress cron

[Timer] 
Persistent=true
Unit=wp-cron.service

[Install]
WantedBy=timers.target

Такой запуск стабилен при низкой посещаемости и даёт прозрачные логи.

Перевод wp-cron на реальный cron или systemd‑таймер

Отладка, безопасность и «краевые случаи»

Надёжное расписание — это не только «когда запускать», но и «как ограничить вред от ошибок».

  • Окружение. Задавайте PATH, LANG, переменные приложения. Для сложных проектов храните их в .env и загружайте в начале скрипта.
  • Таймзона. Cron и systemd timers используют системную зону. Решите заранее — локальное время или UTC. При переходах на летнее/зимнее время используйте OnCalendar и проверяйте смещение.
  • Ресурсы. На VDS ограничивайте потребление: CPUQuota, MemoryMax, IO*. На виртуальном хостинге снижайте приоритет через nice/ionice.
  • Файловые права. Скрипты выполняются от пользователя cron или systemd‑пользователя. Не пишите логи туда, где нет прав; проверьте владельца каталога логов.
  • Коды возврата. Делайте явный exit 1 при ошибке и логируйте причину, иначе мониторинг не поймёт, что случилось.
  • Тишина — враг. Даже при успехе полезно печатать короткую сводку: «processed=123 duration=4.2s» — это упростит и автоматический разбор, и ручную отладку.
  • Готовность зависимостей. Для сервисов, которым нужен БД/сеть, укажите After=network-online.target или ретраи в скрипте. В cron — добавьте повтор с задержкой.

Чек‑лист перед запуском в прод

  • Команда стабильно отрабатывает вручную и в «чистом» окружении.
  • Есть защита от параллельных запусков: flock или внутренние замки.
  • Логи пишутся и ротируются; при ошибке есть email alerts.
  • Для долгоживущих процессов — systemd с Restart= и ресурсными лимитами.
  • Расписание покрывает перерывы: Persistent=true для timers.
  • Проверены права доступа и таймзона.

Частые ошибки и как их избежать

  • Относительные пути и «оно у меня в шелле работает». Лечится явными путями и PATH в unit/crontab.
  • Случайные дубли задач. Используйте замки или «единственный исполнитель».
  • Молчаливые падения. Лечится кодами возврата, логами и email alerts.
  • Неуправляемые воркеры. На VDS — только systemd, а не вечный nohup.
  • Гигантские лог‑файлы. Включите ротацию и срок хранения.

Итог

Для хостинга — crontab с грамотным окружением, flock, логи и почтовые уведомления. Для VDS — связка systemd timers + сервисные юниты: чёткие расписания, перезапуски, OnFailure, journald и лимиты ресурсов. Отдельно держите под контролем очереди: воркеры должны быть перезапускаемы и наблюдаемы. Такой фундамент снимает массу проблем и делает фоновые задачи предсказуемыми.

Поделиться статьей

Вам будет интересно

Сроки домена без паники: auto‑renew, Grace/Redemption Period и безопасное продление OpenAI Статья написана AI Fastfox

Сроки домена без паники: auto‑renew, Grace/Redemption Period и безопасное продление

Разбираем жизненный цикл домена: что происходит у регистратора и в реестре после expiration, как работают auto‑renew, grace и rede ...
HTTP Security Headers на практике: CSP, Permissions‑Policy, Referrer‑Policy и X‑Frame‑Options в Nginx и Apache OpenAI Статья написана AI Fastfox

HTTP Security Headers на практике: CSP, Permissions‑Policy, Referrer‑Policy и X‑Frame‑Options в Nginx и Apache

Покажу, как включить и отладить ключевые HTTP security headers — CSP, Permissions‑Policy, Referrer‑Policy и X‑Frame‑Options — в Ng ...
Большие загрузки и выдача файлов: client_max_body_size, upload_max_filesize, X‑Accel‑Redirect OpenAI Статья написана AI Fastfox

Большие загрузки и выдача файлов: client_max_body_size, upload_max_filesize, X‑Accel‑Redirect

413 Request Entity Too Large, пустой $_FILES, обрывы по таймаутам и «тяжёлая» раздача через PHP. Разбираем Nginx+PHP: лимиты и тай ...