Magento

Magento 2 cron jobs

by , , revisited on


Goal: Setup PROPER Magento 2 cron jobs

The following are suggested crons from Magento 2 documentation. Assuming that your Magento 2 installation is in /var/www:

* * * * * /usr/bin/php /var/www/bin/magento cron:run | grep -v "Ran jobs by schedule" >> /var/www/var/log/magento.cron.log
* * * * * /usr/bin/php /var/www/update/cron.php >> /var/www/var/log/update.cron.log
* * * * * /usr/bin/php /var/www/bin/magento setup:cron:run >> /var/www/var/log/setup.cron.log

This is wrong for at least a couple reasons.

Magento 2 crons and memory

Cron tasks usually require more RAM than web scripts. Magento 2 recommended PHP memory_limit is 768M.

So we want to remove memory limitations for Magento cron jobs only. The proper crons now become:

* * * * * /usr/bin/php -d memory_limit=-1 /var/www/bin/magento cron:run | grep -v "Ran jobs by schedule" >> /var/www/var/log/magento.cron.log
* * * * * /usr/bin/php -d memory_limit=-1 /var/www/update/cron.php >> /var/www/var/log/update.cron.log
* * * * * /usr/bin/php -d memory_limit=-1 /var/www/bin/magento setup:cron:run >> /var/www/var/log/setup.cron.log

Now your Magento 2 cron jobs will run without any memory limitation by PHP. Great.

Magento 2 crons and fatal PHP errors

It may happen to you as it happened to me. A severely bad coded, beta quality plugin caused failed cron runs with absolutely no logging.
This is because by default PHP error_log is empty and the cron definitions we had so far only redirect standard output to the log files.

Let’s make things right:

* * * * * /usr/bin/php -d memory_limit=-1 /var/www/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule" >> /var/www/var/log/magento.cron.log
* * * * * /usr/bin/php -d memory_limit=-1 /var/www/update/cron.php 2>&1 >> /var/www/var/log/update.cron.log
* * * * * /usr/bin/php -d memory_limit=-1 /var/www/bin/magento setup:cron:run 2>&1 >> /var/www/var/log/setup.cron.log

You’ll notice that we’ve added 2>&1 to each cron job. This redirects error output to standard output. So everything included fatal PHP errors is now being logged to corresponding files.

Alert emails?

Cron has a feature that is annoying to some and wonderful to the others. That is, sending an email when a cron job outputs something. This is good to be alerted when something doesn’t work as expected. So you may want to modify your cron jobs, to output only errors (those will be sent by email) while still logging everything:

* * * * * /usr/bin/php -d memory_limit=-1 /var/www/bin/magento cron:run 2> >(tee -a /var/www/var/log/magento.cron.log >&1) > >(grep -v "Ran jobs by schedule" >> /var/www/var/log/magento.cron.log) 
* * * * * /usr/bin/php -d memory_limit=-1 /var/www/update/cron.php 2> >(tee -a /var/www/var/log/update.cron.log >&1) >> /var/www/var/log/update.cron.log
* * * * * /usr/bin/php -d memory_limit=-1 /var/www/bin/magento setup:cron:run 2> >(tee -a /var/www/var/log/setup.cron.log >&1) >> /var/www/var/log/setup.cron.log

This will log both errors and regular output to the log files. And it will also output errors to standard output, which cron will email to us. How in the world does this work? 🙂

Let’s review the first defined cron job bits:

  • 2> >(tee -a /var/www/var/log/magento.cron.log >&1): this redirects stderr (2>) to a command substitution. The command substitution has a format of >(...). In our case it uses tee to log to file as well as output to stdout.
  • Note that the order of redirections is important. Read left to right: we now output stderr to current destination of stdout and file. And that’s it for stderr. It won’t pick up on subsequent redefinition of stdout destination. That got me puzzled when initially understanding how redirections order works. The keyword here is current.
  • Next bit > >(grep -v "Ran jobs by schedule" >> /var/www/var/log/magento.cron.log) redirects stdout to a command substitution: which filters for a message that we never want to log, and logs everything else the log file and outputs to stdout.

Now:

  • We will get an email once a cron fails with an error
  • We can easily expand the above crons to log errors to a different file.

The command substitution parts of our crons is supported by bash and not sh. So if you’re in doubt which is the one your cron uses, specify it in your cron. Just add a line at the top of all the cron definitions:

SHELL=/bin/bash

Now we have proper Magento 2 cron jobs setup. You can checkout Paperttrail for cloud-based aggregated logging facility for your Magento log files.

Magento 2 update cron tip

If Magento 2 was installed via composer, you have to run composer install inside update folder to make update cron succeed.

  1. Mage Lover

    Great article. Cron job is a way to automate taks.

    I have found another guide to setup cron job using custom module in Magento 2: https://magenticians.com/setup-cron-job-magento-2/

    Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.