Whenever 使用教程

Whenever 是一個 Ruby gem,它提供了清晰的語法用於編寫和部署 cron jobs。本文翻譯自它的 Github:https://github.com/javan/when...html

安裝

$ gem install whenever

或者寫到 Gemfile,配合Bundle:java

gem 'whenever', require: false

開始

$ cd /apps/my-great-project
$ bundle exec wheneverize .

爲你建立初始化配置文件 config/schedule.rb (只要你的目錄下有 config 文件夾)。git

whenever 命令

whenever 命令只是將 schedule.rb 文件的內容輸出爲 cron 語法結構,並不會讀取和寫入你的 crontab 文件。github

$ cd /apps/my-great-project
$ bundle exec whenever

若是要將這些任務寫入到 crontab 文件中去,帶參數執行命令:api

$ whenever --update-crontab

其餘經常使用命令:ruby

$ whenever --user app # set a user as which to install the crontab
$ whenever --load-file config/my_schedule.rb # set the schedule file
$ whenever --crontab-command 'sudo crontab' # override the crontab command
提示:若是你運行 whenever --update-crontab 沒有附帶 --user 選項,所生成的 cron 將只能被當前用戶執行。這意味着若是你所執行的任務須要其餘用戶的權限,將失敗。

可使用 crontab -l 列出當前當前系統的任務列表。bash

運行 whenever --help,輸出一些用於調度的選項、調度變量以及其餘內容。服務器

schedule.rb 文件例子

every 3.hours do # 1.minute 1.day 1.week 1.month 1.year is also supported
  # the following tasks are run in parallel (not in sequence)
  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 # Many shortcuts available: :hour, :day, :month, :year, :reboot
  runner "SomeModel.ladeeda"
end

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

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

# run this task only on servers with the :app role in Capistrano
# see Capistrano roles section below
every :day, at: '12:20am', roles: [:app] do
  rake "app_server:task"
end

定義本身的工做類型

Whenever 內置三種類型的工做:command,runner 以及 rake。你能夠經過定義job_type,來定義你本身的工做類型。app

舉個例子:ide

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

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

這段例子的意思是,每兩個小時,執行一次 /usr/local/bin/awesome party extreme:task 老是做爲第一個參數,額外的參數被替換其餘傳遞的內容,或者使用 set 定義的變量。

whenever 中,默認的工做類型定義以下:

job_type :command, ":task :output"
job_type :rake,    "cd :path && :environment_variable=:environment bundle exec rake :task --silent :output"
job_type :runner,  "cd :path && bin/rails runner -e :environment ':task' :output"
job_type :script,  "cd :path && :environment_variable=:environment bundle exec script/:task :output"

Rails 3 以前的應用程序,和不使用 Bundler 的應用程序,將分別從新定義 rake 和runner,以使其正常運行。

若是 :path 沒有設置,使用當前whenever執行的目錄。:environment_variable 變量默認使用 RAILS_ENV:environment 默認設置爲production:outpuot用於配置你的輸出重定向,能夠在(這裏)[http://github.com/javan/whene...],瞭解到如何配置。

全部的工做默認經過 bash -l -c 'command' 來執行。這會使你的 cron job 加載整個環境變量,而不是 cron 執行的有限環境。這讓你的 rvm 工做的更好。瞭解更多:http://github.com/javan/whene...

你能夠經過定義 :job_template 來改變這一默認行爲。

set :job_template, "bash -l -c ':job'"

設置 :job_setemplate 爲空,來恢復標準行爲:

set :job_template, nil

解析日期和時間

Whenever 使用 (Chronic)[https://github.com/mojombo/ch...] gem,來解析指定的日期和時間。

若是默認的 Chronic 配置不適合你,你能夠自定義。

舉一個例子,使用24小時制,來替換默認的12小時制:

set :chronic_options, hours24: true

# By default this would run the job every day at 3am
every 1.day, at: '3:00' do
  runner "MyModel.nightly_archive_job"
end

能夠在這裏找到配置選項:
https://github.com/mojombo/chronic/blob/master/lib/chronic/parser.rb

經過 MAILTO 環境變量,自定義 email 接收對象

工做的結果,能夠輸出到電子郵件地址,經過 MAILTO 環境變量來配置。

多種方式能夠配置郵件接受地址:

全局配置例子:

env 'MAILTO', 'output_of_cron@example.com'

every 3.hours do
  command "/usr/bin/my_great_command"
end

只在一個代碼塊中生效的例子:

every 3.hours, mailto: 'my_super_command@example.com'  do
  command "/usr/bin/my_super_command"
end

只在一個工做中生效的例子:

every 3.hours do
  command "/usr/bin/my_super_command", mailto: 'my_super_command_output@example.com'
end

Capistrano 集成

使用內置的 Capistrano recipe,便可完成簡單的 crontab 部署時更新。 Capistrano V3 的使用,將在下一節介紹。

打開 "config/deploy.rb" 文件:

require "whenever/capistrano"

在這裏https://github.com/javan/whenever/blob/master/lib/whenever/capistrano/v2/recipes.rb 你能夠找到 recipe 可使用的配置項。好比你想使用 bundler:

set :whenever_command, "bundle exec whenever"
require "whenever/capistrano"

若是你想在不一樣的環境中使用(如 staging,production),你能夠這麼用:

set :whenever_environment, defer { stage }
require "whenever/capistrano"

capistrano 變量 :stage 保存着當前環境的名稱。這將在 schedule.rb 文件中提供正確的 :environment。

若是你的兩個環境,在同一臺服務器上,你須要爲他們提供命名空間,不然將在部署時相互覆蓋:

set :whenever_environment, defer { stage }
set :whenever_identifier, defer { "#{application}_#{stage}" }
require "whenever/capistrano"

若是你要在別的路徑開啓調度,你須要這樣配置:

set :whenever_load_file, defer { "#{release_path}/somewhere/else/schedule.rb" }
require "whenever/capistrano"

Capistrano V3 Integration

打開你的 "Capfile" 文件:

require "whenever/capistrano"

查看文件底部的 load:default task 以瞭解能夠配置的選項。舉個例子,crontab 的 application 或 stage 命名空間條目的行爲,在 "config/deploy.rb" 文件中配置。

set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" }

集成 Capistrano,默認指望 :application 變量被設置,以便在 crontab 中肯定做業範圍。

Capistrano 權限

關於權限,首先要知道的是它是徹底可選的,以及向後兼容。若是你不須要 Crontabs 部署不一樣的工做,在不一樣的服務器上,你能夠中止閱讀,並放心的跳過這塊的內容,一切都工做的很好。

當你在 schedule.rb 文件中定義工做的時候,默認它會被分發到全部在 whenever_roles 列表中的服務器。(該列表默認爲 [:db]):

very :day, at: '12:20am' do
  rake 'foo:bar'
end

若是咱們在 deploy.rb 中,設置 whenever_roles 爲 [:db, :app],以及 schedule.rb 中加入工做:

every :day, at: '1:37pm', roles: [:app] do
  rake 'app:task' # will only be added to crontabs of :app servers
end

every :hour, roles: [:db] do
  rake 'db:task' # will only be added to crontabs of :db servers
end

every :day, at: '12:02am' do
  command "run_this_everywhere" # will be deployed to :db and :app servers
end

簡單的規則:

  1. 若是 whenever_roles 中,未列出服務器的角色,則永遠不會將做業添加到他的 crontab 中。
  2. 若是 whenever_roles 中,包含服務器的角色,那麼將在其 crontab 中添加全部做業,若是包含 :roles 參數,這些做業將被列出。
  3. 若是做業有 :roles 參數,但角色不在 whenever_roles 列表中,則做業不會被部署到任何服務器上

RVM Integration

若是你的產品生產環境,使用 RVM(Ruby Version Manager),你將會遇到一個致使你的 cron job 掛起的陷阱。這與 whenever 並沒有直接關聯,調試起來很麻煩。你的 .rvmrc 文件必須被可信,不然 cron jobs 將掛起等待該文件受信任。一個解決辦法是,將這一行添加到 ~/.rvmrc 中,來禁止這個提示。

rvm_trust_rvmrcs_flag=1

這表示 rvm 將信任全部的 rvmrc 文件。

Heroku?

Heroku 不支持 cron,做爲替代,提供了Heroku Scheduler。若是你要部署到 Herku,你要使用它,而不是 Whenever。

Testing

whenever-test 是一個 Whenever 的擴展,用於測試 Whenever schedule。

Credit

Whenever 的誕生,是爲了使用 Inkling(http://inklingmarkets.com/)。能夠在這裏進行了解:http://blog.inklingmarkets.co...

謝謝全部貢獻者,是他們讓 Whenever 變得更好:http://github.com/javan/whene...

討論/反饋/提問/Bugs

通常的討論和問題,請訪問 google group:http://groups.google.com/group/whenever-gem

若是你遇到大 bug 或者問題,可使用 github 的 issue:http://github.com/javan/whene...

Ryan Bates 建立了一份很好的關於 Whenever 的 Railscast:http://railscasts.com/episode... 可能有些過期,可是個很好的開始。

相關文章
相關標籤/搜索