cron snippets

How to execute a CakePHP controller's action from a cron job

Tagged cakephp, cron, job  Languages php

First copy webroot/index.php to webroot/cron_scheduler.php. Replace everything below require CORE_PATH . 'cake' . DS . 'bootstrap.php'; with the following code:

#
# BEGIN
#
# This was added to webroot/cron_scheduler.php
#

# Check that URI was specified and that we're called from the command line (not the web)
if($argc == 2 && php_sapi_name() === "cli") 
{
    # Set request URI
    $_SERVER['REQUEST_URI'] = $argv[1];
    # Set user-agent, so we can do custom processing
    $_SERVER['HTTP_USER_AGENT'] = 'cron';
    
    $Dispatcher= new Dispatcher();
    $Dispatcher->dispatch($argv[1]);
} 

#
# END
#
# 
#

Now you can execute CakePHP from the command line with the following command:

$ php cron_scheduler.php /controller/action

If you get the following error, remove the lines containing line feeds in bootstrap.php:

Warning: Cannot modify header information - headers already sent by (output started at .../app/config/b
ootstrap.php:48) in .../app/app_controller.php on line 46

Scheduling jobs to run daily, weekly or monthly with Cron

Tagged cron, scheduling, daily, weekly, monthly  Languages bash

Cron syntax and valid values:

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

Below are a few examples on how to run a script every 10 minutes, every 30 minutes, every hour, daily, weekly, monthly.

Execute crontab -e and add the following (see man crontab):

# Every 10 minutes
*/10 * * * * /home/belsebub/delete_old_stuff.sh

# Every 30 minutes
*/30 * * * * /home/belsebub/delete_old_stuff.sh

# Every 60 minutes
*/60 * * * * /home/belsebub/delete_old_stuff.sh

# Every day at 00:00
00 00 * * * /home/belsebub/delete_old_stuff.sh

# Every saturday at 00:00
00 00 * * 6 /home/belsebub/delete_old_stuff.sh

# First day of every month at 00:00
00 00 1 * * /home/belsebub/delete_old_stuff.sh

On Debian the configuration goes to /var/spool/cron/crontabs/username.

Running (and debugging) cronjobs with rbenv and bundler

Tagged rbenv, backup, cron, bundler  Languages bash

This snippet shows how to run a backup script (Backup gem) and how to debug cron in case it doesn't work.

This example uses bundler and rbenv to complicate things:

# Set the path to include rbenv
PATH=$PATH:/home/xxx/.rbenv/shims/:/home/xxx/.rbenv/bin/:/bin:/usr/bin/

# Debug cron environment...
*/1 * * * * /bin/bash -l -c '/bin/env > /tmp/cron-env.log'

# Run backup every 12 hours
* */12 * * * /bin/bash -l -c 'eval "$(rbenv init -)" && cd /var/www/xxx/current && bundle exec backup perform --trigger xxx -c config/backup.rb >> /tmp/backup.log 2>&1'

If backup fails, check /tmp/backup.log and/or /tmp/cron-env.log.

How to parse a cronline/crontab/cron with Ruby

Tagged cron, cronline, ruby  Languages ruby

You can use the rufus-scheduler gem to parse cronline/crontab/cron with Ruby.

Gemfile:

gem 'rufus-scheduler'

Example:

require 'rufus/scheduler/cronline'
cron = Rufus::Scheduler::CronLine.new("00 00 1 * *") # 00:00 every first day of the month
#
next_time = cron.next_time(Time.current)
previous_time = cron.previous_time(Time.current)

rufus-scheduler's cronline implementation: https://github.com/jmettraux/rufus-scheduler/blob/master/lib/rufus/scheduler/cronline.rb

See tests for details and syntax: https://github.com/jmettraux/rufus-scheduler/blob/master/spec/cronline_spec.rb

Cron configuration examples.

How to get notified when a Cron job fails

Tagged cron, alert, notify  Languages 

To get notified when a cron script fails you can tell cron to send any errors to you by email.

It already does this by default, but the emails are sent to the Unix account's mailbox:

cat /var/spool/mail/<username> | less

To use a different email address use the MAILTO setting as described here:

MAILTO=email@example.com
0 */2 * * * /bin/backup.sh > /dev/null

Cron will now send an email whenever the script (/bin/backup.sh) prints something to stderr.

If the script is printing to stderr without it failing try Cronic:

0 */2 * * * cronic /bin/backup.sh

You can of course also try to fix the script by not printing to STDERR unless it's really an error.

Check the mail log to see if it's working:

sudo tail -f /var/log/mail.log

If you're email server is rejecting emails sent by cron you might need to set the MAILFROM variable. However, only some cron version supports MAILFROM.

Testing Whenever with Rspec

Tagged cron, rspec, whenever  Languages ruby
require 'spec_helper'
require 'whenever'

describe Whenever do
  def gen_cron(stage:)
    x = Whenever::JobList.new(
      file: Rails.root.join("config", "schedule.rb").to_s,
      set: "stage=#{stage}"
    ).generate_cron_output
    x.gsub(Dir.pwd, "")
  end

  it "generates correct cron configuration for each stage" do
    [ :qa, :production ].each do |stage|
      expected = File.read("spec/fixtures/#{stage}.cron")
      cron = gen_cron(stage: stage)
      # NOTE: Uncomment to update expected cron configuration
      #File.open("spec/fixtures/#{stage}.cron", "w") {|x| x << cron }
      assert_equal expected.strip, cron.strip
    end
  end
end