Cron Jobs 101

Scheduling Tasks with Cron Jobs

Cron Jobs are used for scheduling tasks to run on the server. They’re most commonly used for automating system maintenance or administration. However, they are also relevant to web application development. There are many situations when a web application may need certain tasks to run periodically. Today we are going to explore the fundamentals of Cron Jobs.

Definitions

First let’s familiarize ourselves with the terms related to this subject.

“Cron” is a time-based job scheduler in Unix-like operating systems (Linux, FreeBSD, Mac OS etc…). And these jobs or tasks are referred to as “Cron Jobs”.

There is a cron “daemon” that runs on these systems. A daemon is a program that runs in the background all the time, usually initiated by the system. This cron daemon is responsible for launching these cron jobs on schedule.

The schedule resides in a configuration file named “crontab”. That’s where all the tasks and their timers are listed.

Why Use Cron Jobs?

Server admins have been using cron jobs for a long time. But since the target audience of this article is web developers, let’s look at a few use cases of cron jobs that are relevant in this area:

  • If you have a membership site, where accounts have expiration dates, you can schedule cron jobs to regularly deactivate or delete accounts that are past their expiration dates.
  • You can send out daily newsletter e-mails.
  • If you have summary tables (or materialized views) in your database, they can be regularly updated with a cron job. For example you may store every web page hit in a table, but another summary table may contain daily traffic summaries.
  • You can expire and erase cached data files in a certain interval.
  • You can auto-check your website content for broken links and have a report e-mailed to yourself regularly.
  • You can schedule long-running tasks to run from a command line script, rather than running it from a web script. Like encoding videos, or sending out mass e-mails.
  • You can even perform something as simple as fetching your most recent Tweets, to be cached in a text file.

Syntax

Here is a simple cron job:

10 * * * * /usr/bin/php /www/virtual/username/cron.php > /dev/null 2>&1

There are two main parts:

  1. The first part is “10 * * * *”. This is where we schedule the timer.
  2. The rest of the line is the command as it would run from the command line.

The command itself in this example has three parts:

  1. “/usr/bin/php”. PHP scripts usually are not executable by themselves. Therefore we need to run it through the PHP parser.
  2. “/www/virtual/username/cron.php”. This is just the path to the script.
  3. “> /dev/null 2>&1″. This part is handling the output of the script. More on this later.

Timing Syntax

This is the first part of the cron job string, as mentioned above. It determines how often and when the cron job is going to run.

It consists of five parts:

  1. minute
  2. hour
  3. day of month
  4. month
  5. day of week

Here is an illustration:

Asterisk

Quite often, you will see an asterisk (*) instead of a number. This represents all possible numbers for that position. For example, asterisk in the minute position would make it run every minute.

We need to look at a few examples to fully understand this Syntax.

Examples:

This cron job will run every minute, all the time:

* * * * * [command]

This cron job will run at minute zero, every hour (i.e. an hourly cron job):

0 * * * * [command]

This is also an hourly cron job but run at minute 15 instead (i.e. 00:15, 01:15, 02:15 etc.):

15 * * * * [command]

This will run once a day, at 2:30am:

30 2 * * * [command]

This will run once a month, on the second day of the month at midnight (i.e. January 2nd 12:00am, February 2nd 12:00am etc.):

0 0 2 * * [command]

This will run on Mondays, every hour (i.e. 24 times in one day, but only on Mondays):

0 * * * 1 [command]

You can use multiple numbers separated by commas. This will run three times every hour, at minutes 0, 10 and 20:

0,10,20 * * * * [command]

Division operator is also used. This will run 12 times per hour, i.e. every 5 minutes:

*/5 * * * * [command]

Dash can be used to specify a range. This will run once every hour between 5:00am and 10:00am:

0 5-10 * * * [command]

Also there is a special keyword that will let you run a cron job every time the server is rebooted:

@reboot [command]

Setting Up and Managing Cron Jobs

There are a few different ways to create and manage your cron jobs.

Control Panels

Many web hosting companies provide control panels for their customers. If you are one of them, you might be able to find a section in your control panel to manage your cron jobs.

Editing the Crontab

Running this command will launch vi (text editor) and will let you edit the contents of the crontab:

crontab -e

So it would help to be familiar with the basic vi commands as it is quite different than any other text editor you might have worked with.

If you would just like to see the existing crontab without editing it, you can run this command:

crontab -l

To delete the contents of the crontab:

crontab -r

Loading a File

You can write all of your cron jobs into a file and then push it into the crontab:

crontab cron.txt

Be careful, because this will overwrite all existing cron jobs with this files contents, without warning.

Comments

You can add comments followed by the # character.

# This cron job does something very important
10 * * * * /usr/bin/php /www/virtual/username/cron.php > /dev/null 2>&1

Setting the E-mail

As I mentioned earlier, by default the output from the crons get sent via e-mail, unless you discard them or redirect them to a file. The MAILTO setting let’s you set or change which e-mail address to send them to:

MAILTO="username@example.com"
# This cron job does something very important
10 * * * * /usr/bin/php /www/virtual/username/cron.php > /dev/null 2>&1

Using the PHP Parser

CGI scripts are executable by default, but PHP scripts are not. They need to run through the PHP parser. That’s why we need to put the path to the parser before the path of the script.

* * * * * /usr/bin/php [path to php script]

Sometimes it might be under another location like: “/usr/local/bin/php”. To find out, you can try running this in the command line:

which php

Handling the Output

If you do not handle the output of the cron script, it will send them as e-mails to your user account on the server.

Discarding Output

If you put “> /dev/null 2>&1″ at the end of the cron job command (or any command), the output will be discarded.

The closing bracket (>) is used for redirecting output. “/dev/null” is like a black hole for output. Anything that goes there is ignored by the system.

This part “2>&1″ causes the STDERR (error) output to be redirected to the STDOUT (normal) output. So that also ends up in the “/dev/null”.

Outputting to a File

To store the cron output in a file, use the closing bracket (>) again:

10 * * * * /usr/bin/php /www/virtual/username/cron.php > /var/log/cron.log

That will rewrite the output file every time. If you would like to append the output at the end of the file instead of a complete rewrite, use double closing bracket (>>) instead:

10 * * * * /usr/bin/php /www/virtual/username/cron.php >> /var/log/cron.log

Executable Scripts

Normally you need to specify the parser at the beginning of the command as we have been doing. But there is actually a way to make your PHP scripts executable from the command line like a CGI script.

You need is to add the path to the parser as the first line of the script:

#!/usr/local/bin/php

Also make sure to set proper chmod (like 755) to make the file executable.

When you have an executable script, the cron job can be shorter like this:

10 * * * * /www/virtual/username/hello.php

Preventing Cron Job Collision

In some cases you may have frequent running cron jobs, and you may not want them to collide if they take longer to run than the frequency itself.

For example, you may have a cron job running every minute. Yet, every once in a while it may take longer than one minute to run. This can cause another instance of the same cron script to start running before the previous one finishes. You can create too many busy processes this way and possibly crash the server if they keep slowing down each other, and cause even more processes to be created over time..

This problem can be addressed via file locking, and more specifically the non-blocking (LOCK_NB) type of file locks. (If you are not familiar with file locking, I suggest you read about it first.)

You can add this code to the cron job script:

$fp = fopen('/tmp/lock.txt', 'r+');

if(!flock($fp, LOCK_EX | LOCK_NB)) {
    echo 'Unable to obtain lock';
    exit(-1);
}

/* ... */

fclose($fp);

With regular file locks the flock() function call would block the script if there is an existing lock. And it would release once that lock is gone. However, with a non-blocking lock, such as in the code above, the function call does not stop the script, but it immediately returns FALSE if there is an existing lock. So in this case, we can immediately exit the script when we see there is an existing lock, which indicates that another cron job is currently running.

Blocking Web Access to Cron Jobs

When you write a cron job in a web scripting language like PHP, you may want to make sure that nobody can execute it by just loading it from their browser. One easy option would be to store these script outside of your web folder. However this may not be practical or preferable for some developers, if they want to keep their cron job scripts right within their web application folders.

If you put all of the cron job scripts in a folder, you block access by putting this line in an .htaccess file:

deny from all

Or you can also deny access to scripts on an individual basis by putting this line at the beginning:


if (isset($_SERVER['REMOTE_ADDR'])) die('Permission denied.');

This will ensure that, when the script is accessed from the web, it will abort immediately.

Conclusion

Thank you for reading. Even though cron jobs just seem like a tool just for system admins, they are actually relevant to many kinds of web applications.

Please leave your comments and questions, and have a great day!

Write a Plus Tutorial

Did you know that you can earn up to $600 for writing a PLUS tutorial and/or screencast for us? We’re looking for in depth and well-written tutorials on HTML, CSS, PHP, and JavaScript. If you’re of the ability, please contact Jeffrey at nettuts@tutsplus.com.

Please note that actual compensation will be dependent upon the quality of the final tutorial and screencast.

Write a PLUS tutorial

Add Comment

Discussion 66 Comments

Comment Page 1 of 21 2
  1. DeannRie says:

    Nice Thx!!!

  2. Thanks for this tut; such a coincidence, a friend was explaining some of this to me just yesterday! I’m going to have to give a few cron jobs a try.

    • Eugene says:

      Same here! I had a problem. Needed to update currency list from another time, but didn’t know how to automate it. Buddy explained, but still I didn’t quite understand it. Hope this article will a great deal of help as other articles presented here.

  3. Furley says:

    perfect timing. I was just setting up something like this.

  4. great tutorial this is a common thing which every developer should know

  5. Ryan says:

    Is there a version of Cron for ASP.NET?

  6. Keith says:

    Such a useful article. Thanks Burak!

  7. Neil says:

    You left out possibly the most useful cron job: scheduled database backups!

    Otherwise, a good tutorial for those unfamilar with cron.

  8. Daniel Whyte says:

    Nice, i should start using cron, would make life easier

  9. fractalbit says:

    This is excellent! And the video tutorial by Jeff super awesome! Since i am new to this, allow me a few questions.

    I want to bulid a basic vista/7 gadget that reads a feed and display the results. Can i use jquery and YQL to achieve this?

    Also, i would love if you could make a tutorial about building vista/7 gadgets. Since the technologies used are xml/html/javascript i believe it really has a place in this site.

    Thanks anyway!

  10. Alexander says:

    Nice, never such a complete and practical article about cronjobs

  11. wow! Nice article, I always wondering what exactly Cron Jobs were, now I anderstand.

  12. Brilliant never understood Cron Jobs but this will certainly help

  13. Fynn says:

    Nice! I was just thinking to use Cron Jobs to update a 10mb XML feed.

  14. piyanistll says:

    thanks for tutorial very nice!

  15. Web Canedo says:

    Cron Job is extremally useful. Thanks for sharing…

  16. Scott says:

    Awesome! I’ve been meaning to look further into Cron Jobs. This seems like a good start.

  17. abdulla says:

    very nice tut…

    thanx very much

  18. Ben says:

    Should be more information on Unix commands not just timing.

  19. Indrek says:

    Great job Burak!
    Your articles are always explained very thoroughly and you cover every aspect.

    Actually I’m not sure if I’ve ever read a more thorough article about the use of crontab.

    After not using crontabs via command line for some time now it was great updating my knowledge again.

  20. Adawo says:

    Thx for this tutorial ;)

  21. Giedrius says:

    Nice tutorial :-) Great job!

  22. n0ta says:

    Really nice tut! Perfect to take some stress away from our Web Applications.

    Thanks for sharing

  23. Sajid Ali says:

    Thank you for the nice tutorial, keep it up.

  24. Shane says:

    I only knew what cron jobs were, not how to configure and run them, so this tutorial is a nicely written chunk of relevant information!

    Thanks.

  25. Franck says:

    Once again, nice tut !
    Thank you Burak.

  26. Great article, I use a cron schedule every day.

  27. Davidmoreen says:

    Where has this been my entire programing life? I have been searching for a php script that chacks itself without a page load! Thanks for the tut.

  28. jem says:

    excellent article!

  29. Seth says:

    I would love to see this topic taken further into the world of making DB backups and then saving that file to a local computer rather than your local hosting setup.

  30. jmarreros says:

    thanks, it is so usefull, I ‘m sure I going to apply this information in the future

  31. Michael says:

    V nice!
    Will be bookmarking this for future reference when my brain fails me.

  32. DemoGeek says:

    Great Tut! Would have kicked up a notch if Burak must have used a practical example to illustrate. But, hey, still a great Tut!

    I think it will but just wanted to make sure…let’s say your PHP script took a fatal error, will Cron dump the error to the log file if specified? Or do we need to configure it to do so?

    • MrC says:

      Most cron systems will email any output to the accounts registered cron address (can set it in the sites control panel – usually in or around the cron overview page)

    • Michael says:

      If you are using the ‘> /path/to/myLog.log 2>&1′ param, then all output and errors will be redirected to your log file (anything that would normally show in the console if ran from the command line).

      If you want specific logging on your script, do it inside the script you are running. Use exception catching :)

  33. That’s great !

    Thanks !

    Cool !

  34. John Shaw says:

    Hi,

    I’m having an issue on CentOS 5 with my cron jobs. Every time the job runs, I get an email back saying it couldn’t open the input file: /home/user/script.php

    I don’t know why this is, as all the paths are correct and I’ve set everything up accordingly.

    I was wondering if anyone knows of a GUI interface for CentOS that I could use to set up my cron jobs.

    More information about my issue here:
    https://www.centos.org/modules/newbb/viewtopic.php?topic_id=24430&start=0#forumpost97114

  35. Run more than 5 cron jobs on Media Temple Grid Hosting…

    http://thegraphicdesignshop.com/content/run-more-than-5-cron-jobs-on-media-temple-grid-hosting/

    because this will be a problem you run into down the road ;)

  36. krzysko says:

    Thanks. This tut is very edify;)

  37. adbox says:

    nicly presented. 2cents – I use a free service to manage my cronjobs. http://www.cronwatch.com

  38. waterhidden says:

    Nice article.

    I recommend http://www.weetasks.com to schedule some url free, as I do, without writing any code.

  39. Winston says:

    Hi..
    Any way i could allow the cron to perform even though the linux account is loacked (passwd expired)

  40. Alex Bongo says:

    Great tutorial Burak! You’ll be amazed to know the numbers of Developers who don’t know how Cron Jobs could save them 100% on Automation needs! I’m one of them! I used to think Cron is for Unix/Linux Administrators on their blacky CLI windows! Sincerely, you have added great values to my development/automation skills!

  41. Nice Tut. Very Helpful when explaining Cron tasks.

    Btw. Is there a good web developer practice for pinging Search Engines to your site, for when your site is updated? Does anyone do this through cron tasks?

    I will probably incorporate this with a mysql database where it flushes the dB every two days, to keep everything fresh and new. But what other things can you do with this?

  42. Hyder says:

    wow .. brilliant article on cron job !However ,another section could have been added about how to do task scheduling on Windows :) If anyone is looking for info like this then go to START – > All programs -> Accessories -> Systems and look for Task scheduler .

  43. DooPromotion says:

    Nice post. Buy My host can not use cron job. I want run cron job for run something process. How can i do?

  44. Greg says:

    Excellent tut like usual. Bravo Burak.

  45. RebateSense says:

    This is great from a plain vanilla PHP point of view, but I guess very few uses the plain vanilla PHP these days given the capabilities of some of the frameworks. Would be even great if there is an in-depth tut that explains the nuts and bolts of dealing with crons on a few of these frameworks, for example, CodeIgniter.

  46. Sandeep says:

    That was awesome post.

    Thanks a lot…

Comment Page 1 of 21 2

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.