← Back to javan/whenever

How to Deploy & Use javan/whenever

Whenever: Cron Jobs in Ruby

Whenever is a Ruby gem that provides a clear syntax for writing and deploying cron jobs.

Prerequisites

  • Ruby: A Ruby environment (version compatible with your project) is required.
  • Bundler (recommended): For managing gem dependencies.
  • Cron daemon: A running cron daemon on the target system to execute the scheduled tasks.

Installation

You can install Whenever as a gem or include it in your project's Gemfile.

As a Gem

$ gem install whenever

With Bundler (Gemfile)

Add the following line to your Gemfile:

gem 'whenever', require: false

Then, run bundle install to install the gem:

$ bundle install

Configuration

Whenever uses a config/schedule.rb file to define your cron jobs.

Initializing schedule.rb

Navigate to your project's root directory and run wheneverize:

$ cd /apps/my-great-project # Replace with your project path
$ bundle exec wheneverize .

This command creates an initial config/schedule.rb file. Ensure the config directory exists in your project.

Defining Cron Jobs

Edit config/schedule.rb to define your tasks.

Basic Scheduling

every 3.hours do
  runner "MyModel.some_process"
  rake "my:rake:task"
  command "/usr/bin/my_great_command"
end

every 1.day, at: '4:30 am' do
  runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end

every 1.day, at: ['4:30 am', '6:00 pm'] do
  runner "Mymodel.task_to_run_in_two_times_every_day"
end

every :hour do # Shortcuts: :hour, :day, :month, :year, :reboot
  runner "SomeModel.ladeeda"
end

every :sunday, at: '12pm' do # Days of the week, :weekend, :weekday
  runner "Task.do_something_great"
end

every '0 0 27-31 * *' do # Raw cron syntax
  command "echo 'you can use raw cron syntax too'"
end

Custom Job Types

Define your own job types using job_type:

job_type :awesome, '/usr/local/bin/awesome :task :fun_level'

every 2.hours do
  awesome "party", fun_level: "extreme"
end

Whenever ships with command, runner, and rake job types. Their definitions are:

job_type :command, ":task :output"
job_type :rake,    "cd :path && :environment_variable=:environment :bundle_command rake :task --silent :output"
job_type :script,  "cd :path && :bundle_command script/:task :output"
job_type :runner,  "cd :path && :bundle_command :runner_command -e :environment ':task' :output"

Default values for job types:

  • :path: Defaults to the directory where whenever was executed.
  • :environment_variable: Defaults to 'RAILS_ENV'.
  • :environment: Defaults to 'production'.
  • :output: Configures output redirection (see Whenever Wiki for details).

Environment Variables and Settings

  • Job Template: By default, jobs run with bash -l -c 'command...'. You can change this:
    set :job_template, "bash -l -c ':job'"
    # Or disable it:
    set :job_template, nil
    
  • Chronic Options: Customize how Whenever parses dates and times using set :chronic_options:
    set :chronic_options, hours24: true
    
    Refer to the Chronic gem documentation for available options.
  • Email Recipient (MAILTO): Configure where job output is sent.
    • Global:
      env 'MAILTO', 'output_of_cron@example.com'
      
    • Per interval block:
      every 3.hours, mailto: 'my_super_command@example.com' do
        command "/usr/bin/my_super_command"
      end
      
    • Per job:
      every 3.hours do
        command "/usr/bin/my_super_command", mailto: 'my_super_command_output@example.com'
      end
      

Comments

Add descriptions to your cron entries:

every 1.hours, description: "My job description" do
  command "/usr/bin/my_great_command"
end

Build & Run

Whenever does not "run" in the traditional sense; it generates cron syntax that is then installed into your system's crontab.

Previewing Cron Output

To see the cron syntax generated from your config/schedule.rb without modifying your crontab:

$ cd /apps/my-great-project # Replace with your project path
$ bundle exec whenever

This command will output the cron entries to your console.

## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated.
## [message] Run `whenever --help' for more options.

Deployment

Deployment with Whenever involves writing the generated cron jobs to the system's crontab.

Updating the Crontab

To write the cron jobs defined in config/schedule.rb to your system's crontab:

$ whenever --update-crontab

Common Options for whenever --update-crontab

  • Specify User: Install the crontab for a specific user. This is crucial for tasks requiring different user permissions.
    $ whenever --update-crontab --user app
    
    Note: If --user is not specified, cron jobs are generated for the current user.
  • Specify Schedule File: Use a different schedule file.
    $ whenever --update-crontab --load-file config/my_schedule.rb
    
  • Override Crontab Command: Use a custom command to interact with crontab (e.g., for sudo).
    $ whenever --update-crontab --crontab-command 'sudo crontab'
    

Listing Installed Cron Jobs

You can verify the installed cron jobs using the standard crontab -l command:

$ crontab -l

Clearing Crontab Entries

To remove Whenever-managed cron entries from your crontab:

$ whenever --clear-crontab

Capistrano Integration

Whenever includes Capistrano recipes for automated deployment.

In your deploy.rb or Capistrano configuration:

# Add to your Capfile
# require 'whenever/capistrano'

# In deploy.rb
set :whenever_roles,        :db # Default: :db
set :whenever_identifier,   -> { fetch :application } # Default: application name
set :whenever_environment,  -> { fetch :rails_env, fetch(:stage, "production") } # Default: production
set :whenever_variables,    -> { "environment=#{fetch :whenever_environment}" }
set :whenever_path,         -> { fetch :latest_release } # Default: latest release path

# To update crontab on deploy:
after "deploy:symlink:release", "whenever:update_crontab"

# To clear crontab on rollback:
after "deploy:rollback", "whenever:update_crontab"

The Capistrano tasks are:

  • whenever:update_crontab: Updates the crontab entries on the specified roles.
  • whenever:clear_crontab: Clears Whenever-managed crontab entries.

Troubleshooting

  • Cron jobs not running:
    • Check crontab: Use crontab -l to ensure the jobs are actually installed.
    • User permissions: Verify that the cron jobs are installed for the correct user (whenever --update-crontab --user <username>). Tasks requiring specific user permissions will fail if run by the wrong user.
    • Environment: Cron's environment is often minimal. Ensure your schedule.rb sets necessary environment variables or uses bash -l -c (Whenever's default job_template) to load a full environment, especially for RVM/rbenv setups.
    • Paths: Ensure all commands (e.g., rake, runner, custom scripts) have their full paths or that your PATH environment variable is correctly set within the cron environment.
    • Output: Check the logs or email configured in MAILTO for any error messages.
  • whenever command not found:
    • If using Bundler, ensure you prefix commands with bundle exec (e.g., bundle exec whenever --update-crontab).
    • Verify the gem is installed (gem list whenever).
  • config/schedule.rb not found:
    • Ensure you are running whenever from your project's root directory.
    • Confirm the file exists at config/schedule.rb or specify its path with --load-file.
  • Syntax errors in schedule.rb:
    • Whenever will report Ruby syntax errors when you run whenever. Correct these in your schedule.rb file.
  • Time parsing issues:
    • If at: options are not behaving as expected, check your set :chronic_options in schedule.rb and refer to the Chronic gem documentation for parsing rules.