{"id":22,"date":"2018-09-27T13:46:56","date_gmt":"2018-09-27T13:46:56","guid":{"rendered":"http:\/\/tamer-az.com\/?p=22"},"modified":"2018-09-27T13:46:56","modified_gmt":"2018-09-27T13:46:56","slug":"scheduling-tasks-with-cron-jobs","status":"publish","type":"post","link":"https:\/\/tamer-az.com\/?p=22","title":{"rendered":"Scheduling Tasks with Cron Jobs"},"content":{"rendered":"\n<p>Cron Jobs are used for scheduling tasks to run on the server. They&#8217;re\n most commonly used for automating system maintenance or administration.\n However, they are also relevant to web application development. There \nare many situations when a web application may need certain tasks to run\n periodically. Today we are going to explore the fundamentals of Cron \nJobs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Definitions<\/h3>\n\n\n\n<p>First let&#8217;s familiarize ourselves with the terms related to this subject.<\/p>\n\n\n\n<p>&#8220;Cron&#8221; is a time-based job scheduler in Unix-like operating systems \n(Linux, FreeBSD, Mac OS etc&#8230;). And these jobs or tasks are referred to\n as &#8220;Cron Jobs&#8221;.<\/p>\n\n\n\n<p>There is a cron &#8220;daemon&#8221; that runs on these systems. A daemon is a \nprogram that runs in the background all the time, usually initiated by \nthe system. This cron daemon is responsible for launching these cron \njobs on schedule.<\/p>\n\n\n\n<p>The schedule resides in a configuration file named &#8220;crontab&#8221;. That&#8217;s where all the tasks and their timers are listed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why Use Cron Jobs?<\/h3>\n\n\n\n<p>Server admins have been using cron jobs for a long time. But since \nthe target audience of this article is web developers, let&#8217;s look at a \nfew use cases of cron jobs that are relevant in this area:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>If you have a membership site, where accounts have expiration dates,\n you can schedule cron jobs to regularly deactivate or delete accounts \nthat are past their expiration dates.<\/li><li>You can send out daily newsletter e-mails.<\/li><li>If you have summary tables (or materialized views) in your database,\n they can be regularly updated with a cron job. For example you may \nstore every web page hit in a table, but another summary table may \ncontain daily traffic summaries.<\/li><li>You can expire and erase cached data files in a certain interval.<\/li><li>You can auto-check your website content for broken links and have a report e-mailed to yourself regularly.<\/li><li>You can schedule long-running tasks to run from a command line \nscript, rather than running it from a web script. Like encoding videos, \nor sending out mass e-mails.<\/li><li>You can even perform something as simple as fetching your most recent Tweets, to be cached in a text file. <\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Syntax<\/h3>\n\n\n\n<p>Here is a simple cron job:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>10 * * * * \/usr\/bin\/php \/www\/virtual\/username\/cron.php > \/dev\/null 2>&amp;1<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>There are two main parts:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>The first part is &#8220;10 * * * *&#8221;. This is where we schedule the timer.<\/li><li>The rest of the line is the command as it would run from the command line.<\/li><\/ol>\n\n\n\n<p>The command itself in this example has three parts:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>&#8220;\/usr\/bin\/php&#8221;. PHP scripts usually are not executable by themselves. Therefore we need to run it through the PHP parser.<\/li><li>&#8220;\/www\/virtual\/username\/cron.php&#8221;. This is just the path to the script.<\/li><li>&#8220;> \/dev\/null 2>&amp;1&#8221;. This part is handling the output of the script. More on this later.<\/li><\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Timing Syntax<\/h3>\n\n\n\n<p>This is the first part of the cron job string, as mentioned above. It\n determines how often and when the cron job is going to run.<\/p>\n\n\n\n<p>It consists of five parts:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>minute<\/li><li>hour<\/li><li>day of month<\/li><li>month<\/li><li>day of week<\/li><\/ol>\n\n\n\n<p>Here is an illustration:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/cdn.tutsplus.com\/net\/uploads\/legacy\/550_cron\/1.png\" alt=\"\"\/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Asterisk<\/h4>\n\n\n\n<p>Quite often, you will see an asterisk (*) instead of a number. This \nrepresents all possible numbers for that position. For example, asterisk\n in the minute position would make it run every minute.<\/p>\n\n\n\n<p>We need to look at a few examples to fully understand this Syntax.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Examples:<\/h4>\n\n\n\n<p>This cron job will run every minute, all the time:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>* * * * * [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>This cron job will run at minute zero, every hour (i.e. an hourly cron job):<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>0 * * * * [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>This is also an hourly cron job but run at minute 15 instead (i.e. 00:15, 01:15, 02:15 etc.):<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>15 * * * * [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>This will run once a day, at 2:30am:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>30 2 * * * [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>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.):<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>0 0 2 * * [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>This will run on Mondays, every hour (i.e. 24 times in one day, but only on Mondays):<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>0 * * * 1 [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>You can use multiple numbers separated by commas. This will run three times every hour, at minutes 0, 10 and 20:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>0,10,20 * * * * [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Division operator is also used. This will run 12 times per hour, i.e. every 5 minutes:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>*\/5 * * * * [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Dash can be used to specify a range. This will run once every hour between 5:00am and 10:00am:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>0 5-10 * * * [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Also there is a special keyword that will let you run a cron job every time the server is rebooted:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>@reboot [command]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<h3 class=\"wp-block-heading\">Setting Up and Managing Cron Jobs<\/h3>\n\n\n\n<p>There are a few different ways to create and manage your cron jobs.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Editing the Crontab<\/h4>\n\n\n\n<p>Running this command will launch vi (text editor) and will let you edit the contents of the crontab:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>crontab -e<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/cdn.tutsplus.com\/net\/uploads\/legacy\/550_cron\/5.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>So it would help to be familiar with the <a href=\"http:\/\/www.cbu.edu\/ietc\/faq\/vifaq.html\">basic vi commands<\/a> as it is quite different than any other text editor you might have worked with.<\/p>\n\n\n\n<p>If you would just like to see the existing crontab without editing it, you can run this command:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>crontab -l<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/cdn.tutsplus.com\/net\/uploads\/legacy\/550_cron\/6.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>To delete the contents of the crontab:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>crontab -r<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/cdn.tutsplus.com\/net\/uploads\/legacy\/550_cron\/7.png\" alt=\"\"\/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Loading a File<\/h4>\n\n\n\n<p>You can write all of your cron jobs into a file and then push it into the crontab:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>crontab cron.txt<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Be careful, because this will overwrite all existing cron jobs with this files contents, without warning.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Comments<\/h4>\n\n\n\n<p>You can add comments followed by the # character.<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>12<\/td><td><code># This cron job does something very important<\/code><code>10 * * * * \/usr\/bin\/php \/www\/virtual\/username\/cron.php > \/dev\/null 2>&amp;1<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<h4 class=\"wp-block-heading\">Setting the E-mail<\/h4>\n\n\n\n<p>As I mentioned earlier, by default the output from the crons get sent\n via e-mail, unless you discard them or redirect them to a file. The \nMAILTO setting let&#8217;s you set or change which e-mail address to send them\n to:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>123<\/td><td><code>MAILTO=\"username@example.com\"<\/code><code># This cron job does something very important<\/code><code>10 * * * * \/usr\/bin\/php \/www\/virtual\/username\/cron.php > \/dev\/null 2>&amp;1<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<h3 class=\"wp-block-heading\">Using the PHP Parser<\/h3>\n\n\n\n<p>CGI scripts are executable by default, but PHP scripts are not. They \nneed to run through the PHP parser. That&#8217;s why we need to put the path \nto the parser before the path of the script.<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>* * * * * \/usr\/bin\/php [path to php script]<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Sometimes it might be under another location like: \n&#8220;\/usr\/local\/bin\/php&#8221;. To find out, you can try running this in the \ncommand line:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>which php<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/cdn.tutsplus.com\/net\/uploads\/legacy\/550_cron\/2.png\" alt=\"\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Handling the Output<\/h3>\n\n\n\n<p>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.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Discarding Output<\/h4>\n\n\n\n<p>If you put &#8220;> \/dev\/null 2>&amp;1&#8221; at the end of the cron job command (or any command), the output will be discarded.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/cdn.tutsplus.com\/net\/uploads\/legacy\/550_cron\/3.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>The closing bracket (>) is used for redirecting output. \n&#8220;\/dev\/null&#8221; is like a black hole for output. Anything that goes there is\n ignored by the system.<\/p>\n\n\n\n<p>This part &#8220;2>&amp;1&#8221; causes the STDERR (error) output to be \nredirected to the STDOUT (normal) output. So that also ends up in the \n&#8220;\/dev\/null&#8221;.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Outputting to a File<\/h4>\n\n\n\n<p>To store the cron output in a file, use the closing bracket (>) again:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>10 * * * * \/usr\/bin\/php \/www\/virtual\/username\/cron.php > \/var\/log\/cron.log<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>That will rewrite the output file every time. If you would like to \nappend the output at the end of the file instead of a complete rewrite, \nuse double closing bracket (>>) instead:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>10 * * * * \/usr\/bin\/php \/www\/virtual\/username\/cron.php >> \/var\/log\/cron.log<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<h3 class=\"wp-block-heading\">Executable Scripts<\/h3>\n\n\n\n<p>Normally you need to specify the parser at the beginning of the \ncommand as we have been doing. But there is actually a way to make your \nPHP scripts executable from the command line like a CGI script.<\/p>\n\n\n\n<p>You need is to add the path to the parser as the first line of the script:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>12345678<\/td><td><code>#!\/usr\/local\/bin\/php<\/code><code>&lt;?php<\/code>\u00a0<code>echo<\/code> <code>\"hello world\\n\"<\/code><code>;<\/code>\u00a0<code>\/\/ ...<\/code>\u00a0<code>?><\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Also make sure to set proper chmod (like 755) to make the file executable.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/cdn.tutsplus.com\/net\/uploads\/legacy\/550_cron\/8.png\" alt=\"\"\/><\/figure>\n\n\n\n<p>When you have an executable script, the cron job can be shorter like this:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>10 * * * * \/www\/virtual\/username\/hello.php<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<h3 class=\"wp-block-heading\">Preventing Cron Job Collision<\/h3>\n\n\n\n<p>In some cases you may have frequent running cron jobs, and you may \nnot want them to collide if they take longer to run than the frequency \nitself.<\/p>\n\n\n\n<p>For example, you may have a cron job running every minute. Yet, every\n once in a while it may take longer than one minute to run. This can \ncause another instance of the same cron script to start running before \nthe previous one finishes. You can create too many busy processes this \nway and possibly crash the server if they keep slowing down each other, \nand cause even more processes to be created over time..<\/p>\n\n\n\n<p>This problem can be addressed via file locking, and more specifically\n the non-blocking (LOCK_NB) type of file locks. (If you are not familiar\n with file locking, I suggest you <a href=\"http:\/\/php.net\/manual\/en\/function.flock.php\">read about it<\/a> first.)<\/p>\n\n\n\n<p>You can add this code to the cron job script:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>01020304050607080910<\/td><td><code>$fp<\/code> <code>= <\/code><code>fopen<\/code><code>(<\/code><code>'\/tmp\/lock.txt'<\/code><code>, <\/code><code>'r+'<\/code><code>);<\/code>\u00a0<code>if<\/code><code>(!<\/code><code>flock<\/code><code>(<\/code><code>$fp<\/code><code>, LOCK_EX | LOCK_NB)) {<\/code><code>echo<\/code> <code>'Unable to obtain lock'<\/code><code>;<\/code><code>exit<\/code><code>(-1);<\/code><code>}<\/code>\u00a0<code>\/* ... *\/<\/code>\u00a0<code>fclose(<\/code><code>$fp<\/code><code>);<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>With regular file locks the flock() function call would block the \nscript if there is an existing lock. And it would release once that lock\n is gone. However, with a non-blocking lock, such as in the code above, \nthe function call does not stop the script, but it immediately returns \nFALSE if there is an existing lock. So in this case, we can immediately \nexit the script when we see there is an existing lock, which indicates \nthat another cron job is currently running.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Blocking Web Access to Cron Jobs<\/h3>\n\n\n\n<p>When you write a cron job in a web scripting language like PHP, you \nmay want to make sure that nobody can execute it by just loading it from\n their browser. One easy option would be to store these script outside \nof your web folder. However this may not be practical or preferable for \nsome developers, if they want to keep their cron job scripts right \nwithin their web application folders.<\/p>\n\n\n\n<p>If you put all of the cron job scripts in a folder, you block access by putting this line in an .htaccess file:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>deny from all<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>Or you can also deny access to scripts on an individual basis by putting this line at the beginning:<\/p>\n\n\n\n<table class=\"wp-block-table\"><tbody><tr><td>1<\/td><td><code>if<\/code> <code>(isset(<\/code><code>$_SERVER<\/code><code>[<\/code><code>'REMOTE_ADDR'<\/code><code>])) <\/code><code>die<\/code><code>(<\/code><code>'Permission denied.'<\/code><code>);<\/code><\/td><\/tr><\/tbody><\/table>\n\n\n\n<p>This will ensure that, when the script is accessed from the web, it will abort immediately.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cron Jobs are used for scheduling tasks to run on the server. They&#8217;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&#8217;s<\/p>\n<div class=\"clearfix\"><\/div>\n<div class=\"pull-left padding-top-25\"><a href=\"https:\/\/tamer-az.com\/?p=22\" class=\"btn btn-theme\">Continue reading<span class=\"screen-reader-text\"> &#8220;Scheduling Tasks with Cron Jobs&#8221;<\/span> <i class=\"fa fa-fw fa-long-arrow-right\"><\/i> <\/a>  <\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,4],"tags":[],"class_list":["post-22","post","type-post","status-publish","format-standard","hentry","category-cpanel","category-linux"],"_links":{"self":[{"href":"https:\/\/tamer-az.com\/index.php?rest_route=\/wp\/v2\/posts\/22","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tamer-az.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tamer-az.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tamer-az.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tamer-az.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=22"}],"version-history":[{"count":1,"href":"https:\/\/tamer-az.com\/index.php?rest_route=\/wp\/v2\/posts\/22\/revisions"}],"predecessor-version":[{"id":25,"href":"https:\/\/tamer-az.com\/index.php?rest_route=\/wp\/v2\/posts\/22\/revisions\/25"}],"wp:attachment":[{"href":"https:\/\/tamer-az.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=22"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tamer-az.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=22"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tamer-az.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=22"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}