Configuring cron jobs

Cron is a daemon that executes commands at specified intervals. These commands are called "cron jobs." Cron is available on Unix, Linux and Mac servers. Windows servers use a Scheduled Task to execute commands.

There is a video, How To: Setting up Drupal's Cron that talks about cron and shows various ways of configuring it.

The cron command

In the following example, the crontab command shown below will activate the cron tasks automatically on the hour:

0 * * * * wget -O - -q -t 1 http://www.example.com/cron.php

In the above sample, the 0 * * * * represents when the task should happen. The first figure represents minutes – in this case, on the "zero" minute, or top of the hour. (If the number were, say, 10, then the action would take place at 10 minutes past the hour.) The other figures represent, respectively, hour, day, month and day of the week. A * is a wildcard, meaning "every time."

The rest of the line basically tells the server to "ping" the url http://www.example.com/cron.php. NOTE: The -O is "dash capital O", not "dash zero". Yes, the capital O is important. Lowercase o won't work

Here is a diagram of the general crontab syntax, for illustration:

# +---------------- minute (0 - 59)
# | +------------- hour (0 - 23)
# | | +---------- day of month (1 - 31)
# | | | +------- month (1 - 12)
# | | | | +---- day of week (0 - 7) (Sunday=0 or 7)
# | | | | |
* * * * * command to be executed

Thus, the cron command example above means "ping http://www.example.com/cron.php at the zero minute on every hour of every day of every month of every day of the week."

How Drupal uses cron

Every Drupal install requires regular actions to handle maintenance tasks such as cleaning up log files and checking for updates. Cron.php is the file that Drupal uses to run the maintenance process.

For instance, if your site were www.example.com, loading the URL http://www.example.com/cron.php in your browser would run the maintenance.

This page is automatically set up when you install Drupal. Simply loading the URL will run the maintenance. Nothing more is required.

For a modest personal site, you might set up this cron job to run once a day. For a more active site you might want to run that job more often—perhaps every few hours or every hour. This regular visit will tell Drupal to perform its periodic tasks, and this will help keep your system running smoothly.

How to set up a cron job

Cron jobs are scheduled by setting up a "crontab." A crontab is a text file that contains the commands to be run. This file can be created and edited either through the command line interface, or, if you manage your website through a web-based control panel such as cpanel or Plesk, you will use the web interface. Check with your hosting company for detailed instructions if you are using a web-based control panel.

To edit a crontab through the command line, type:

crontab -e

If this fails, see the Troubleshooting Cron section below.

Add ONE of the following lines:

45 * * * *  /usr/bin/lynx -source http://example.com/cron.php

45 * * * * /usr/bin/wget -O - -q -t 1 http://www.example.com/cron.php

45 * * * * curl --silent --compressed http://example.com/cron.php

This would have a lynx, wget, or curl visit your cron page 45 minutes after every hour.

Three options are provided in case either wget, lynx or curl are not installed on the server. Any will do the job well.

Learn more about the crontab file syntax here to set up the cron job to run more or less often.

There are many ways to configure a cron job. If you have full access to crontab features, you should be able to simply paste in one of the above example commands – be sure to replace "example.com" with your own web domain or docroot.

If you're on shared hosting, you should be able to find cron job configuration somewhere in your hosting control panel. Some hosts even have cron "wizards" that walk you through the cron configuration, making it much easier if cron is new to you. On a Windows system you can accomplish the same thing with scheduled tasks to launch Internet Explorer pointed to the URL.

Some hosting companies do not permit local loopback, so using wget, curl or lynx will not work. If this is the case, and they run PHP as a CGI (check with your hosting company to see if this is the case), the following will run the cron locally:-

/usr/bin/php /home/sites/example.com/public_html/cron.php

Some hosting companies don’t allow access to cron

If your hosting company restricts access to cron you have many options.

  • Ask the company to give you access, or to set up a cron job for you
  • Ask someone else with access to a server to set up a cron job for you. Any Unix, Linux, or Mac server with access to the internet can have a cron job to regularly visit your site. There are also some companies that offer cron services.
  • Use the Poor Man's Cron module.
  • Find an online cron service. Many are free but with restrictions.

Cron doesn't guarantee your commands will run at the specified interval. But Drupal will try its best to come as close as possible. The more you visit cron.php, the more accurate cron will be.

Troubleshooting cron jobs

If you receive a permission denied error after starting crontab -e, you may need to use sudo:

sudo crontab -e

You may need to adjust the path to wget, lynx or curl in your crontab. For example, the cron example listed above contains the line:

45 * * * *  /usr/bin/lynx -source http://example.com/cron.php

However, Lynx may be in a different location on your server, or not installed at all. To find out where Lynx is installed, enter:

whereis lynx

or

which lynx

If it is not located at /usr/bin/lynx adjust the path as needed. The same applies for wget and curl. If none are installed ask a server administrator for help.

It may be necessary to change http://example.com/cron.php to the location of your Drupal installation. For example, if you have Drupal installed in a subdirectory, it might be http://www.example.com/drupal/cron.php).

Example scripts

Drupal ships with two example scripts in the scripts directory, cron-curl.sh and cron-lynx.sh. You can call these scripts from cron as well:

45 * * * * /home/www/drupal/scripts/cron-lynx.sh

Note that the scripts will need to be updated with the path to your directory and URL.

Running cron as an authenticated user

#!/bin/sh
# Reference http://drupal.org/node/479948#comment-1673488 by pearlbear

SITE=https://dev.example.com/
USERNAME=user.name
PASS=ChangeMe!!12

COOKIES=/tmp/cron-cookies.txt
WGETPARAMS="--quiet -O /dev/null --no-check-certificate --save-cookies $COOKIES --keep-session-cookies --load-cookies $COOKIES"
# if you run drupal in a default language different than English you need to modify this
LOGIN="Log%20in"

wget $WGETPARAMS "${SITE}user"
wget $WGETPARAMS --post-data="name=$USERNAME&pass=$PASS&op=$LOGIN&form_id=user_login" "${SITE}user"
wget $WGETPARAMS " ${SITE}cron.php"

Security notes

It is possible to run cron.php directly via scripts/drupal.sh with Drupal 6. Drupal.sh allows a Drupal page to be executed from a shell script. To do so, add the following cron job to run as the Apache user.

/full/path/to/drupal.sh --root /full/path/to/site/root/ http://default/cron.php

Note that http://default/cron.php is NOT shown as an example, it should be used as is, without changes.

Taking this approach allows cron.php to be blocked to prevent remote access.

To block remote access to cron.php, in the server, .htaccess or vhost configuration file add this section:

    <Files "cron.php">
        Order Deny,Allow
        Deny from all
        Allow from localhost
        Allow from 127.0.0.1
        Allow from xx.xx.xx.xx <-- your IP address
    </Files>

If you take this approach and use drupal.sh to call cron.php, it is probably best not to use the root user to run the cron job. A non-privileged user account, or the Apache account user, for example http-service or www-data, is a better choice. To do so, call crontab -e when logged in as a non-privileged user, or for the Apache account on a Debian server, for example, you can add a user parameter:

sudo crontab -e -u www-data

The downside to this method is that any URLs generated by cron jobs using this method will not be properly formed, starting with "http://default/".

Tips and tricks

Cron Sandbox is a useful site for testing cron entries.

Multiple sites

If you run many sites, you can use this tip to make managing your cron jobs easier. To minimize the clutter, create a /etc/cron.5min directory and have crontab read this directory every five minutes.

*/5 * * * * root run-parts /etc/cron.5min

Then place multiple individual files into the /etc/cron.5min directory, one for each site. The files can be named "site1", "site2", etc. -- note that run-parts may fail to detect files which contain a dot (.) in their name. To make sure that all of your files are visible to cron, type this at a shell prompt:

$ sudo run-parts --test /etc/cron.5min
and make sure that all of your files are listed.

Each of the files in /etc/cron.5min should contain one line:

/usr/bin/lynx -source http://(full site URL)/cron.php > /dev/null 2>&1
or, alternatively, one of the curl or wget commands specified above.

If this doesn't work, try putting another line at the start of each file:

#!/bin/sh
and make sure that the files are executable by doing

$ sudo chmod u+x /etc/cron.5min/*

For more information about using cron in a multisite configuration, see the Multisite Cron section of this guide.

SSL

When using SSL, add one additional argument when calling wget: --no-check-certificate. Do not put “--no-check-certificate” between the -0 and the -.

45 * * * * /usr/bin/wget --no-check-certificate --quiet -O - https://example.com/cron.php

Configuring an editor for cron

You can specify which text editor (emacs, vi, nano, etc.) you want to use to edit the crontab. To tell the system which editor you want to use, type:

export EDITOR=nano

MacOSX crontab

lsw - October 27, 2009 - 15:45

On the Mac you may be getting an error after using crontab -e

crontab: temp file must be edited in place

This seems to be a problem with the way vim works with it's backup files, and can be fixed by adding the following line to your ~/.vimrc

set backupskip=/tmp/*,/private/tmp/*

Now using crontab -e will work.

Setting up Crontab for Drupal--info that helped me

cburn - February 15, 2010 - 17:37

I found this post which helped me set up my crontab on my host http://www.ktechdesign.com/node/82 . I had searched everywhere and could not find anything that really helped with the actual command on the script (the timing I got), but this did and it works perfectly for me!

cburn

Patch to inspect per-module cron execution times

davidwhthomas - February 23, 2010 - 00:57

Here's a patch to add per-module cron execution times to the watchdog log.
Great for debugging cron issues as it allows to to time each cron hook.

In common.inc drupal_cron_run() - replace the lines ( around line 2698 in D6 )

<?php
// Iterate through the modules calling their cron handlers (if any):
module_invoke_all('cron');
?>

with this:

Drupal 5

<?php
// Iterate through the modules calling their cron handlers (if any):
$cron_timer = variable_get('cron_timer', '1'); // can add to settings form, defaults to on
if ($cron_timer) {
 
// start timer for cron total
 
timer_start('cron');
  foreach (
module_implements('cron') as $module) {
   
$function = $module .'_cron';
   
// start timer for this module, using module cron function name as id
   
timer_start($function);
   
// call cron hook
   
$function();
   
$timer = timer_stop($function);
   
// get total in seconds
   
$total = round($timer['time']/1000, 2);
   
watchdog('cron', t('Cron time elapsed for @module is @secs seconds.', array('@module' => $module, '@secs' => $total) ));
  }
 
$cron_timer = timer_stop('cron');
 
$total = round($cron_timer['time']/1000, 2);
 
watchdog('cron', t('Cron time total was @secs seconds.', array('@secs' => $total) ));
}else{
 
// just run cron
 
module_invoke_all('cron');
}
?>

Drupal 6

<?php
// Iterate through the modules calling their cron handlers (if any):
$cron_timer = variable_get('cron_timer', '1'); // can add to settings form, defaults to on
if ($cron_timer) {
 
// start timer for cron total
 
timer_start('cron');
  foreach (
module_implements('cron') as $module) {
   
$function = $module .'_cron';
   
// start timer for this module, using module cron function name as id
   
timer_start($function);
   
// call cron hook
   
$function();
   
$timer = timer_stop($function);
   
// get total in seconds
   
$total = round($timer['time']/1000, 2);
   
watchdog('cron', t('Cron time elapsed for @module is @secs seconds.'), array('@module' => $module, '@secs' => $total) );
  }
 
$cron_timer = timer_stop('cron');
 
$total = round($cron_timer['time']/1000, 2);
 
watchdog('cron', t('Cron time total was @secs seconds.'), array('@secs' => $total) );
}else{
 
// just run cron
 
module_invoke_all('cron');
}
?>

Note: You'll need to remove the php tags from the above code, they're added for syntax highlighting only.

After cron runs, you can see the timing of each hook recorded in the watchdog log.

Just thought I'd share as I found this very useful.

DT

DT, Thanks for the excellent

vertikal.dk - March 17, 2010 - 17:44

DT,

Thanks for the excellent code, which helped me find a cron process, which timed out. But it helped me to add a small text tellling me which cron-process started, because one might start and never finish. Since your code only reports after the process finishes, you don't know which process hangs or times out.

I added a single line right after the loop start:

...
  timer_start('cron');
  foreach (module_implements('cron') as $module) {
    watchdog('cron', t('Starting cron for @module'), array('@module' => $module));
...

This will add an extra line for each cron process, and only the extra line for the process, which hangs or times out.

Martin

First, thank you for the

armsch6 - March 4, 2010 - 10:43

First, thank you for the page, I appreciate the time it took to create it. I hope you don't mind some productive criticism. I think most people come to this page because they don't know how to configure cron, and they probably have no idea how cron jobs work. I am one of those people. I think I speak for at least 50% of all people who come to this page when I say that all we really want is something like this:

"Your cron command should look like this":
CRON COMMAND HERE

I am assuming this is the purpose of this line:

0 * * * * wget -O - -q -t 1 http://www.example.com/cron.php

I would really appreciate it if there was a line for people who simply don't understand cron jobs so well, and just want to run cron once an hour. If the above line is trying to achieve just that, maybe state it?

Cheers again for the page, it helped me a lot (could have taken less of my time though...)
Arman

cron job

medlife - March 29, 2010 - 15:43

Any one knows how to schedule automatic feed aggregator updates? I have set up a the following cron job but it does not make any difference to my feed aggregator. Any insights?

0 * * * * wget -O - -q -t 1 http://www.example.com/cron.php

thanks,
Medlife

Drupal lover!

wget may need its full

danielhall - March 29, 2010 - 17:25

wget may need its full path

on my system it is: /usr/bin/wget

so it may work after you change in your line: 'wget' to '/path/to/wget'

if you dont know what path wget is under with your server, you can locate it with the command-line:
locate wget

this will help you find the right path on your server and then you use that path in your crontab line.

Hope it helps.

Drupalicon in ascii > .(8)
---------------------------------
Daniel Hall

executing from a shell script

Matt B - April 22, 2010 - 20:32

I've found some hosts allow me to call the cron.php URL via curl, lynx, wget etc, as they block that type of connection from a cron job, but they do allow cron jobs. I found this advice useful:

It is possible to run cron.php directly via scripts/drupal.sh with Drupal 6. Drupal.sh allows a Drupal page to be executed from a shell script. To do so, add the following cron job to run as the Apache user.

/full/path/to/drupal.sh --root /full/path/to/site/root/ http://default/cron.php
Note
that http://default/cron.php is NOT shown as an example, it should be used as is, without changes.

....

The downside to this method is that any URLs generated by cron jobs using this method will not be properly formed, starting with "http://default/".

However, I found that changing 'http://default/cron.php' to be the correct URL (eg http://www.mysite.com/cron.php), URLs generated by the cron jobs are then formed properly. Is there any issue in doing this?

To those who is all fresh on cron jobs

Fauskanger - April 26, 2010 - 06:06

I have no problems understanding that cron jobs make you look like a big questionmark, as I am sitting here as one myself.

I actually found that http://en.wikipedia.org/wiki/Cron_job has just a few examples needed and on http://en.wikipedia.org/wiki/CRON_expression you can what you need to get jiggy with fancy timing :P

[ A quick google-search for cron job examples will get you startet too, I guess.. .. ] /or watch the video

.::.......................................::.
Time doesn't pass, it comes..

Cron line for html authenticated sites

vasudev - June 9, 2010 - 14:10

If a site is access-protected using html authentication, for example using the Secure Site module (http://drupal.org/project/securesite) this line can be used:

45 * * * * curl -u user:pwd --silent --compressed http://www.example.com/cron.php

security and the commandline

ohnobinki - June 23, 2010 - 16:07

I would like to note that a command like ``curl -u user:passwd'' should never be used on a shared server. Passing the password on the command line means that anybody on the server can see the username and password as long as the curl process is alive. Alternatives would be using curl's ~/.netrc file to specify the username and password. See curl(1) for more information on curl.

--
binki

What I would love to know is:

nwwoman - June 21, 2010 - 23:43

What I would love to know is: (1) what to do if the cron command runs fine in the command line interface but not in the crontab and (2) if it's the default for only logged-in user 1 to be able to run cron.php in the browser *and** have it run update status

I have googled, binged, read forums, watched videos, to no avail.

Postscript: Yes, the default is user 1. The permission is site configurations. That answers 2...still working on 1.

 
 

Drupal is a registered trademark of Dries Buytaert.