PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

Cron – grupy, własne joby, harmonogram z panelu admina, debugowanie

by Henryk Tews / wtorek, 13 kwietnia 2021 / Opublikowano w Magento 2

Magento 2 intensywnie korzysta z crona – indeksowanie, wysyłka emaili, czyszczenie sesji, synchronizacja kursów walut. Gdy cron przestaje działać, sklep zaczyna się sypać w nieoczywisty sposób: ceny się nie aktualizują, emaile nie wychodzą, indeksy się starzeją. Pokazuję jak działa system crona w Magento, jak pisać własne joby i jak diagnozować problemy.

Jak Magento 2 obsługuje cron

Magento ma dwa procesy cron uruchamiane z poziomu systemu operacyjnego:

# Dwa wpisy w crontab serwera - uruchamiane co minutę
* * * * * php /var/www/magento/bin/magento cron:run 2>&1
* * * * * php /var/www/magento/bin/magento cron:run --group=index 2>&1

cron:run to scheduler – sprawdza tabelę cron_schedule w bazie, planuje nowe joby i uruchamia te które są gotowe. Sam job nie wykonuje się bezpośrednio w procesie schedulera – Magento uruchamia go jako osobny proces PHP, dzięki czemu jeden zawieszony job nie blokuje pozostałych.

Własny job cron – konfiguracja

Nowy job wymaga dwóch plików: klasy PHP z logiką i pliku konfiguracyjnego crontab.xml.

Klasa jobu:

<?php

declare(strict_types=1);

namespace Vendor\Module\Cron;

use Psr\Log\LoggerInterface;
use Vendor\Module\Model\SyncService;

class SyncExternalPrices
{
    public function __construct(
        private SyncService $syncService,
        private LoggerInterface $logger
    ) {}

    public function execute(): void
    {
        $this->logger->info('SyncExternalPrices: start');

        try {
            $count = $this->syncService->syncPrices();
            $this->logger->info('SyncExternalPrices: zakończono', ['updated' => $count]);
        } catch (\Exception $e) {
            // Loguj błąd, ale nie rzucaj wyjątku dalej
            // Niezłapany wyjątek w cronie = job ze statusem "error" w cron_schedule
            $this->logger->error('SyncExternalPrices: błąd', ['error' => $e->getMessage()]);
        }
    }
}

Konfiguracja w etc/crontab.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="default">
        <job name="vendor_module_sync_prices"
             instance="Vendor\Module\Cron\SyncExternalPrices"
             method="execute">
            <!-- Co godzinę, 15 minut po pełnej -->
            <schedule>15 * * * *</schedule>
        </job>
    </group>
</config>

Harmonogram konfigurowalny z panelu admina

Zamiast hardkodować wyrażenie cron w XML, możesz pozwolić adminowi na zmianę harmonogramu przez konfigurację:

<!-- etc/crontab.xml -->
<job name="vendor_module_sync_prices"
     instance="Vendor\Module\Cron\SyncExternalPrices"
     method="execute">
    <config_path>vendor_module/cron/sync_prices_schedule</config_path>
</job>
<!-- etc/config.xml - wartość domyślna -->
<?xml version="1.0"?>
<config>
    <default>
        <vendor_module>
            <cron>
                <sync_prices_schedule>15 * * * *</sync_prices_schedule>
            </cron>
        </vendor_module>
    </default>
</config>
<!-- etc/adminhtml/system.xml - pole w panelu -->
<field id="sync_prices_schedule" translate="label" type="text" sortOrder="10" showInDefault="1">
    <label>Harmonogram synchronizacji cen</label>
    <backend_model>Magento\Cron\Model\Config\Backend\Cron</backend_model>
    <comment>Format cron: minuty godziny dni miesiące dni-tygodnia</comment>
</field>

Własna grupa cron – izolacja jobów

Domyślna grupa default miesza joby systemowe z Twoimi. Dla jobów długo działających lub wymagających specjalnej konfiguracji warto stworzyć własną grupę:

<!-- etc/cron_groups.xml -->
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/cron_groups.xsd">
    <group id="vendor_module">
        <schedule_generate_every>1</schedule_generate_every>
        <schedule_ahead_for>4</schedule_ahead_for>
        <schedule_lifetime>2</schedule_lifetime>
        <history_cleanup_every>10</history_cleanup_every>
        <history_success_lifetime>60</history_success_lifetime>
        <history_failure_lifetime>600</history_failure_lifetime>
        <use_separate_process>1</use_separate_process>
    </group>
</config>

Uruchomienie własnej grupy:

# Na serwerze - dodaj do crontab
* * * * * php /var/www/magento/bin/magento cron:run --group=vendor_module 2>&1

Debugowanie crona – najczęstsze problemy

# Sprawdź stan tabeli cron_schedule
bin/magento cron:run --group=default

# Podgląd zaplanowanych jobów bezpośrednio w bazie
# SELECT job_code, status, scheduled_at, executed_at, finished_at, messages
# FROM cron_schedule
# WHERE job_code = 'vendor_module_sync_prices'
# ORDER BY scheduled_at DESC LIMIT 20;

# Ręczne uruchomienie konkretnego jobu (Magento 2.4+)
bin/magento cron:run --job-code=vendor_module_sync_prices

# Wyczyść starą historię
bin/magento cron:remove-entries --task=vendor_module_sync_prices

Statusy w tabeli cron_schedule:

Status Znaczenie
pending Zaplanowany, czeka na wykonanie
running Aktualnie wykonywany
success Zakończony pomyślnie
error Rzucił wyjątek – sprawdź kolumnę messages
missed Nie zdążył się uruchomić w oknie czasowym

Cron w DDEV

# Jednorazowe uruchomienie crona w DDEV
ddev exec bin/magento cron:run

# Lub wejdź do kontenera i ustaw crontab
ddev ssh
crontab -e
# Dodaj: * * * * * php /var/www/html/bin/magento cron:run 2>&1

Podsumowanie

Cron w Magento 2 to więcej niż prosty scheduler – to system z grupami, historią, izolacją procesów i konfigurowalnym harmonogramem. Własna grupa cron dla krytycznych jobów, obsługa wyjątków w metodzie execute() i regularne sprawdzanie tabeli cron_schedule pod kątem statusu error – to minimum które warto mieć w każdym projekcie produkcyjnym.

About Henryk Tews

Co możesz przeczytać następne

Redis Streams – Consumer Groups, pending messages, dead letter, integracja z Magento queue
PageBuilder – własny typ zawartości, XML config
Własny indekser – mview.xml, flat table, full/partial reindeksacja, triggerowane przez cron
  • Publikacje
  • O autorze
  • Kontakt

© 2026 Created by

GÓRA
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Zawsze aktywne
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Zarządzaj opcjami
  • Zarządzaj serwisami
  • Zarządzaj {vendor_count} dostawcami
  • Przeczytaj więcej o tych celach
Zobacz preferencje
  • {title}
  • {title}
  • {title}