Rails 定時任務——whenever實現週期性任務

根據項目的進展,咱們須要實現後臺進行定時讀取信息的功能,而最關鍵的實現部分是週期性功能,根據調研,決定使用whenever來實現這一功能。 
github:https://github.com/javan/whenever
php

開發前須要明確的問題

  • whenever是怎樣一種週期性機制?
  • whenever能爲咱們提供什麼功能?
  • whenever爲週期性任務提供了哪些控制方式?

問題解決

whenever週期性機制

咱們來看一下github上面是怎麼說的:css

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

意思就是說,whenever是一個ruby gem,但同時它是基於cron jobs的。 
那麼什麼是cron jobs呢?咱們來看一下維基百科的定義:
mysql

Cron 
crontab命令常見於Unix類Unix操做系統之中,用於設置週期性被執行的指令。該命令從標準輸入設備讀取指令,並將其存放於「crontab」文件中,以供以後讀取和執行。該詞來源於希臘語chronos(χρόνος),原意是時間。 
一般,crontab儲存的指令被守護進程激活,crond經常在後臺運行,每一分鐘檢查是否有預約的做業須要執行。這類做業通常稱爲cron jobs
git

也就是說,crontab是在unix和類unix系統中用來實現週期性功能的指令。在網上搜一下,咱們就會看到不少crontab指令相關的語法。 
根據上述的分析,咱們能夠得出這樣的結論: 
whenever事實上是一個cron翻譯器,它將rails中的ruby代碼翻譯成cron腳本,從而將週期性的任務交給cron來執行。 這樣,經過whenever咱們可使用ruby語言來寫週期性任務代碼,在ruby層控制代碼,而不須要與shell腳本進行切換;另外一方面,咱們會發現,因爲cron命令的強大,它的語法也所以變得很複雜,經過whenever,咱們能夠很方便的實現週期性任務。
github

whenever功能

從github中咱們能夠看到,咱們用來實現定時功能的代碼都已經集成在config/schedule.rb文件中了,如下爲github中的whenever實例:sql

every 3.hours do # 1.minute 1.day 1.week 1.month 1.year is also supported 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 :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爲咱們提供的三種方法,runnerrakecommand,事實上,還有script方法也是whenever默認支持的。除了這四種方法外,wheneverr也提供自定義方法的功能,具體作法參照github上的方法來作便可。shell

whenever控制方法

whenever是十分親民的,它的指令沒有cron命令那麼複雜。下面提供幾種whenever比較經常使用的方法:數據庫

whenever (不帶參數)將schedule.rb 文件中的週期性任務轉化成cron命令顯示出來,但不讀取或者寫入到crontab文件中 whenever -i [identifier] 更新新定時任務,默認更新 schedule.rb 文件中的所有 whenever -w, --write-crontab, --update-crontab, [identifier] 寫定時任務,默認更新 schedule.rb 文件中的所有 whenever -c, --clear-crontab [identifier] 清除 crontab 

 

除此以外,cron命令也是能夠是用的,比較經常使用的是:api

crontab -l [UserName]: 列出目前的時程表 crontab -e [UserName]: 執行文字編輯器(第一次由本身選擇編輯器)來配置crontab的具體執行方法

一個十分簡單的whenever demo

1.添加whenever(Gemfile)

gem 'whenever', :require => false

2.生成config/schedule.rb文件 
執行命令:

wheneverize

3.添加本身的週期性任務 
config/schedule.rb文件中添加:

set :environment, :development every 2.minutes do runner "Timetest.mytime" end

其中,set :environment, :development是設置執行任務時的環境,默認狀況下環境爲production 
上述代碼實現的是每兩分鐘讀取當前時間並存入到數據庫的功能。其中,runner方法執行的方法以下:

class Timetest < ApplicationRecord def self.mytime a = Timetest.new a.time_now = Time.now a.save end end

這樣,在rails中實現whenever的代碼就算是寫完了,真的是簡單到不行啊!(實在忍不住感慨一句) 
下面就要執行週期性任務了。

4.執行週期性任務 
在rails工程文件夾下進行一下操做

  • 更新schedule.rb中的任務到cronjob中
whenever -i

能夠看到這樣的打印結果:

[write] crontab file updated
  • 執行週期性任務
whenever -w

能夠看到:

[write] crontab file written

此時咱們的週期性任務便在後臺運行了,此時查看咱們的任務:

crontab -l

能夠看到如下打印:

# Begin Whenever generated tasks for: /home/vito/rails/test_of_rails/test_rails/config/schedule.rb 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58 * * * * /bin/bash -l -c 'cd /home/vito/rails/test_of_rails/test_rails && bundle exec bin/rails runner -e development '\''Timetest.mytime'\''' # End Whenever generated tasks for: /home/vito/rails/test_of_rails/test_rails/config/schedule.rb

這樣,咱們的週期性任務就算是在順利執行了。

須要注意的一點是運行時crontab的環境(rails和crontab環境不匹配時whenever沒法執行),通常調試時多使用的是development環境,而不設置時默認的是production環境,若是你使用crontab -l發現是production環境,可使用

crontab -e

直接修改成development,或者直接將-e production刪掉便可。

通過上述流程,咱們即可以成功地實現週期性任務了。若是此時你發現本身的週期性任務仍是沒有執行,那你就得好好看看你本身的任務代碼了,極可能是執行的任務代碼自己有問題,而與whenever的實現沒有太大的關係了

相關文章
相關標籤/搜索