1.09

Cron Functionality

Understanding how to configure and run scheduled background tasks in Magento 2.

Topic Overview: Understanding how Magento's cron system works, configuring scheduled jobs, and debugging cron functionality.

Cron System Overview

mindmap root((Cron System)) System Cron UNIX based Triggers pub/cron.php Frequency: 1-15 min Magento Cron Pulls scheduled jobs Executes PHP classes Cron folder Configuration crontab.xml Schedule expression Cron groups Areas crontab default Frontend issues Adminhtml issues Testing Console command Direct execution PHPStorm debug

What is Cron?

Understanding Cron Systems

System Cron (UNIX/Linux/MacOS)
  • Operating system feature
  • Runs tasks on schedule
  • Time-based job scheduler
  • Configured via crontab

Example: Run a script every 5 minutes

*/5 * * * * /path/to/script.sh
Magento Cron
  • Built on top of system cron
  • Executes pub/cron.php
  • Manages internal job scheduling
  • Uses cron_schedule table

Purpose: Background tasks without HTTP requests

How Magento Cron Works

The Cron Workflow

Step-by-Step Process:
  1. System Cron Triggers - OS cron runs pub/cron.php (or bin/magento cron:run)
  2. Magento Pulls Jobs - Queries cron_schedule table for jobs due to run
  3. Executes PHP Classes - Runs the execute() method of each job
  4. Updates Status - Marks jobs as success, error, or missed in database
Important: Frequency is determined by system administrator, typically:
  • Once per minute: * * * * *
  • Once per 5 minutes: */5 * * * *
  • Once per 15 minutes: */15 * * * *

Cron Entry Point

pub/cron.php

The main entry point for Magento cron. System cron should trigger this file.

System Crontab Example:
* * * * * php /var/www/html/pub/cron.php
# Or using bin/magento
* * * * * php /var/www/html/bin/magento cron:run
Critical: The frequency of system cron determines the maximum frequency of Magento cron jobs. If system cron runs every 5 minutes, your Magento jobs cannot run more frequently than every 5 minutes, even if configured for every minute.

Cron Job Structure

Cron Class Location

Cron jobs are PHP classes typically located in the Cron folder of a module:

Example Structure:
app/code/Bonlineco/OrderExport/
├── Cron/
│   └── ExportOrders.php
├── etc/
│   └── crontab.xml
└── registration.php
Example Cron Class:
<?php
namespace Bonlineco\OrderExport\Cron;

class ExportOrders
{
    protected $logger;
    
    public function __construct(
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->logger = $logger;
    }
    
    public function execute()
    {
        $this->logger->info('Cron job started: Export Orders');
        
        // Your cron logic here
        // Export orders, send emails, cleanup, etc.
        
        $this->logger->info('Cron job finished: Export Orders');
        return $this;
    }
}
Key Points:
  • Must have execute() method
  • No parameters in execute()
  • Use dependency injection for dependencies
  • Return $this or void

Configuring Cron Jobs

crontab.xml Configuration

Add a crontab.xml file to your module to register cron jobs:

Location:
app/code/Bonlineco/OrderExport/etc/crontab.xml
Basic Configuration:
<?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="bonlineco_export_orders" instance="Bonlineco\OrderExport\Cron\ExportOrders" method="execute">
            <schedule>*/5 * * * *</schedule>
        </job>
    </group>
</config>
Configuration Elements:
  • <group id="default"> - Cron group (default, index, etc.)
  • name - Unique job identifier
  • instance - PHP class to execute
  • method - Method to call (usually "execute")
  • <schedule> - Cron expression (when to run)

Cron Schedule Expression

Understanding Cron Syntax

Cron expressions consist of 5 fields:

* * * * *
│ │ │ │ │
│ │ │ │ └─── Day of week (0-7, 0 and 7 are Sunday)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)
Common Examples:
Expression Description
* * * * * Every minute
*/5 * * * * Every 5 minutes
0 * * * * Every hour (at minute 0)
0 0 * * * Daily at midnight
0 2 * * * Daily at 2:00 AM
0 0 * * 0 Weekly on Sunday at midnight
0 0 1 * * Monthly on the 1st at midnight
Tip: Use crontab.guru to validate and understand cron expressions!

Cron Groups

Organizing Cron Jobs

Magento uses cron groups to organize and control job execution:

Default Cron Groups:
  • default - General purpose cron jobs
  • index - Indexing operations
  • consumers - Message queue consumers
Configuring Group Settings:

Admin Path: Stores → Configuration → Advanced → System → Cron

Group Configuration Options:
  • Generate Schedules Every - How often to generate new schedules
  • Schedule Ahead For - How far ahead to schedule jobs
  • Missed If Not Run Within - When to mark job as missed
  • History Cleanup Every - How often to clean old records
  • Success History Lifetime - How long to keep successful jobs
  • Failure History Lifetime - How long to keep failed jobs

Cron Area Considerations

Important Area Context

Critical Issue:

All cron jobs execute in the crontab area by default, not frontend or adminhtml.

Problems this causes:

  • Observers registered for frontend/adminhtml won't fire
  • Area-specific configuration may not load
  • Plugins may not work as expected
  • Layout XML won't be processed
Solutions:
  1. Design cron jobs to be area-independent
  2. Manually set area if needed: $this->state->setAreaCode('frontend')
  3. Don't rely on frontend/adminhtml observers in cron
  4. Use global scope observers when possible

Testing and Debugging Cron

Testing Strategies

Method 1: Manual Cron Execution
php bin/magento cron:run

Runs all due cron jobs immediately.

Method 2: Run Specific Group
php bin/magento cron:run --group=default
Method 3: Create Console Command (Recommended)

Why? Makes testing and debugging much easier!

Step 1: Create console command

app/code/Bonlineco/OrderExport/Console/Command/CronRun.php
<?php
namespace Bonlineco\OrderExport\Console\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Bonlineco\OrderExport\Cron\ExportOrders;

class CronRun extends Command
{
    protected $exportOrders;
    
    public function __construct(
        ExportOrders $exportOrders,
        string $name = null
    ) {
        $this->exportOrders = $exportOrders;
        parent::__construct($name);
    }
    
    protected function configure()
    {
        $this->setName('bonlineco:cron:export-orders')
             ->setDescription('Run order export cron job manually');
    }
    
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('Starting order export...');
        $this->exportOrders->execute();
        $output->writeln('Order export completed!');
        return 0;
    }
}

Step 2: Register in di.xml

<type name="Magento\Framework\Console\CommandList">
    <arguments>
        <argument name="commands" xsi:type="array">
            <item name="bonlineco_cron_export" xsi:type="object">
                Bonlineco\OrderExport\Console\Command\CronRun
            </item>
        </argument>
    </arguments>
</type>

Step 3: Run command

php bin/magento bonlineco:cron:export-orders
Method 4: PHPStorm Debugging
  1. Configure PHPStorm to run PHP Script
  2. Point to your console command
  3. Set breakpoints in cron class
  4. Debug with full IDE support!

Checking Cron Status

Using cron_schedule Table

Magento tracks all cron jobs in the cron_schedule table:

Query Recent Cron Jobs:
SELECT 
    job_code, 
    status, 
    scheduled_at, 
    executed_at, 
    finished_at,
    messages
FROM cron_schedule
WHERE job_code = 'bonlineco_export_orders'
ORDER BY scheduled_at DESC
LIMIT 10;
Status Values:
  • pending - Scheduled but not yet run
  • running - Currently executing
  • success - Completed successfully
  • error - Failed with error
  • missed - Didn't run within expected time
CLI Command:
php bin/magento cron:list

Shows all registered cron jobs and their schedules.

Best Practices

Do's
  • Keep cron jobs fast and efficient
  • Use logging for debugging
  • Handle exceptions gracefully
  • Create console commands for testing
  • Use appropriate cron groups
  • Set realistic schedules
  • Monitor cron_schedule table
  • Clean up old cron records
Don'ts
  • Don't run heavy operations every minute
  • Don't rely on frontend/adminhtml area
  • Don't forget error handling
  • Don't assume system cron frequency
  • Don't create long-running jobs (use queues instead)
  • Don't skip logging
  • Don't test only in production

Common Issues and Solutions

Troubleshooting

Issue Cause Solution
Cron not running System cron not configured Add cron entry to system crontab
Jobs always "missed" System cron runs too infrequently Increase system cron frequency or adjust job schedule
Observer not firing Wrong area (crontab vs frontend) Use global observers or set area manually
Job runs too often Schedule expression incorrect Verify cron expression with crontab.guru
Job appears twice Duplicate configuration Check for duplicate entries in crontab.xml

Exam Tips

Key Points to Remember

  • Entry point: pub/cron.php or bin/magento cron:run
  • Configuration file: etc/crontab.xml
  • Cron class location: Cron/ folder in module
  • Required method: execute() with no parameters
  • Cron expression format: 5 fields (minute, hour, day, month, weekday)
  • Default area: crontab (not frontend or adminhtml)
  • Status tracking: cron_schedule database table
  • Common groups: default, index, consumers
  • Frequency limit: System cron frequency determines maximum job frequency
  • Testing tip: Create console command wrapper for easier debugging
  • Configuration: Stores → Configuration → Advanced → System → Cron