whenever 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -1
- data/CHANGELOG.rdoc +27 -0
- data/README.rdoc +40 -28
- data/Rakefile +11 -8
- data/bin/whenever +11 -5
- data/lib/whenever/capistrano.rb +31 -0
- data/lib/whenever/command_line.rb +20 -6
- data/lib/whenever/{outputs/cron.rb → cron.rb} +4 -11
- data/lib/whenever/job.rb +32 -7
- data/lib/whenever/job_list.rb +9 -19
- data/lib/whenever/job_types/default.rb +11 -3
- data/lib/whenever/output_redirection.rb +58 -0
- data/lib/whenever/version.rb +1 -1
- data/lib/whenever.rb +3 -13
- data/test/{command_line_test.rb → functional/command_line_test.rb} +156 -3
- data/test/{output_at_test.rb → functional/output_at_test.rb} +20 -6
- data/test/functional/output_default_defined_jobs_test.rb +145 -0
- data/test/{output_defined_job_test.rb → functional/output_defined_job_test.rb} +25 -1
- data/test/functional/output_env_test.rb +23 -0
- data/test/{output_redirection_test.rb → functional/output_redirection_test.rb} +19 -1
- data/test/test_helper.rb +5 -18
- data/test/{cron_test.rb → unit/cron_test.rb} +1 -1
- data/test/unit/job_test.rb +77 -0
- data/whenever.gemspec +38 -30
- metadata +77 -30
- data/lib/whenever/outputs/cron/output_redirection.rb +0 -60
- data/test/output_command_test.rb +0 -37
- data/test/output_env_test.rb +0 -56
- data/test/output_rake_test.rb +0 -74
- data/test/output_runner_test.rb +0 -175
data/.gitignore
CHANGED
data/CHANGELOG.rdoc
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
== 0.6.1 / October 20th, 2010
|
|
2
|
+
|
|
3
|
+
* Detect script/rails file and change runner to Rails 3 style if found. [Javan Makhmali]
|
|
4
|
+
|
|
5
|
+
* Created a new :job_template system that can be applied to all commands. Wraps all in bash -l -c 'command..' by default now for better RVM support. Stopped automatically setting the PATH too. [Javan Makhmali]
|
|
6
|
+
|
|
7
|
+
* Added a built-in Capistrano recipe. [Javan Makhmali]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
== 0.5.3 / September 24th, 2010
|
|
11
|
+
|
|
12
|
+
* Better regexes for replacing Whenever blocks in the crontab. #45 [Javan Makhmali]
|
|
13
|
+
|
|
14
|
+
* Preserving backslashes when updating existing crontab. #82 [Javan Makhmali]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
== 0.5.2 / September 15th, 2010
|
|
18
|
+
|
|
19
|
+
* Quotes automatically escaped in jobs. [Jay Adkisson]
|
|
20
|
+
|
|
21
|
+
* Added --cut option to the command line to allow pruning of the crontab. [Peer Allan]
|
|
22
|
+
|
|
23
|
+
* Switched to aaronh-chronic which is ruby 1.9.2 compatible. [Aaron Hurley, Javan Makhmali]
|
|
24
|
+
|
|
25
|
+
* Lots of internal reorganizing; tests broken into unit and functional. [Javan Makhmali]
|
|
26
|
+
|
|
27
|
+
|
|
1
28
|
== 0.5.0 / June 28th, 2010
|
|
2
29
|
|
|
3
30
|
* New job_type API for writing custom jobs. Internals use this to define command, runner, and rake. [Javan Makhmali - inspired by idlefingers (Damien)]
|
data/README.rdoc
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
== Introduction
|
|
2
2
|
|
|
3
|
-
Whenever is a Ruby gem that provides a clear syntax for
|
|
4
|
-
|
|
5
|
-
Ryan Bates created a great Railscast about Whenever: http://railscasts.com/episodes/164-cron-in-ruby
|
|
6
|
-
|
|
7
|
-
Discussion: http://groups.google.com/group/whenever-gem
|
|
3
|
+
Whenever is a Ruby gem that provides a clear syntax for writing and deploying cron jobs.
|
|
8
4
|
|
|
9
5
|
== Installation
|
|
10
6
|
|
|
11
|
-
$
|
|
7
|
+
$ gem install whenever
|
|
12
8
|
|
|
9
|
+
Or with Bundler in your Gemfile.
|
|
10
|
+
|
|
11
|
+
gem 'whenever', :require => false
|
|
12
|
+
|
|
13
13
|
== Getting started
|
|
14
14
|
|
|
15
15
|
$ cd /my/rails/app
|
|
@@ -41,7 +41,7 @@ More examples on the wiki: http://wiki.github.com/javan/whenever/instructions-an
|
|
|
41
41
|
|
|
42
42
|
== Define your own job types
|
|
43
43
|
|
|
44
|
-
Whenever ships with three pre-defined job types: command, runner, and rake. You can define your own with
|
|
44
|
+
Whenever ships with three pre-defined job types: command, runner, and rake. You can define your own with `job_type`.
|
|
45
45
|
|
|
46
46
|
For example:
|
|
47
47
|
|
|
@@ -51,43 +51,52 @@ For example:
|
|
|
51
51
|
awesome "party", :fun_level => "extreme"
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
Would run
|
|
54
|
+
Would run `/usr/local/bin/awesome party extreme` every two hours. `:task` is always replaced with the first argument, and any additional `:whatevers` are replaced with the options passed in or by variables that have been defined with `set`.
|
|
55
55
|
|
|
56
56
|
The default job types that ship with Whenever are defined like so:
|
|
57
57
|
|
|
58
|
-
job_type :command,
|
|
59
|
-
job_type :
|
|
60
|
-
job_type :
|
|
58
|
+
job_type :command, ":task :output"
|
|
59
|
+
job_type :rake, "cd :path && RAILS_ENV=:environment rake :task :output"
|
|
60
|
+
job_type :runner, "cd :path && script/runner -e :environment ':task' :output"
|
|
61
|
+
|
|
62
|
+
If a script/rails file is detected (like in a Rails 3 app), runner will be defined to fit:
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
job_type :runner, "cd :path && script/rails runner -e :environment ':task' :output"
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
If a `:path` is not set it will default to the directory in which `whenever` was executed. `:environment` will default to 'production'. `:output` will be replaced with your output redirection settings which you can read more about here: http://github.com/javan/whenever/wiki/Output-redirection-(logging-your-cron-jobs)
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
$ whenever
|
|
68
|
+
All jobs are by default run with `bash -l -c 'command...'`. Among other things, this allows your cron jobs to play nice with RVM by loading the entire environment instead of cron's somewhat limited environment. Read more: http://blog.scoutapp.com/articles/2010/09/07/rvm-and-cron-in-production
|
|
68
69
|
|
|
69
|
-
|
|
70
|
+
You can change this by setting your own job_template.
|
|
71
|
+
|
|
72
|
+
set :job_template, "bash -l -c ':job'"
|
|
73
|
+
|
|
74
|
+
Or set the job_template to nil to have your jobs execute normally.
|
|
75
|
+
|
|
76
|
+
set :job_template, nil
|
|
77
|
+
|
|
78
|
+
And you'll see your schedule.rb converted to cron sytax. Note: running `whenever` with no options does not display your current crontab file, it simply shows you the output of converting your schedule.rb file.
|
|
70
79
|
|
|
71
80
|
== Capistrano integration
|
|
72
81
|
|
|
73
|
-
|
|
82
|
+
Use the built-in Capistrano recipe for easy crontab updates with deploys.
|
|
74
83
|
|
|
75
|
-
|
|
84
|
+
In your "config/deploy.rb" file:
|
|
76
85
|
|
|
77
|
-
|
|
78
|
-
desc "Update the crontab file"
|
|
79
|
-
task :update_crontab, :roles => :db do
|
|
80
|
-
run "cd #{release_path} && whenever --update-crontab #{application}"
|
|
81
|
-
end
|
|
82
|
-
end
|
|
86
|
+
require "whenever/capistrano"
|
|
83
87
|
|
|
84
|
-
|
|
88
|
+
Take a look at the recipe for options you can set. http://github.com/javan/whenever/blob/master/lib/whenever/capistrano.rb
|
|
89
|
+
For example, if you're using bundler do this:
|
|
85
90
|
|
|
86
|
-
|
|
91
|
+
set :whenever_command, "bundle exec whenever"
|
|
92
|
+
require "whenever/capistrano"
|
|
87
93
|
|
|
88
|
-
|
|
94
|
+
== The `whenever` command
|
|
89
95
|
|
|
90
|
-
|
|
96
|
+
$ cd /my/rails/app
|
|
97
|
+
$ whenever
|
|
98
|
+
|
|
99
|
+
This will simply show you your schedule.rb file converted to cron syntax. It does not read or write your crontab file. Run `whenever --help` for a complete list of options.
|
|
91
100
|
|
|
92
101
|
== Credit
|
|
93
102
|
|
|
@@ -101,6 +110,9 @@ For general discussion and questions, please use the google group: http://groups
|
|
|
101
110
|
|
|
102
111
|
If you've found a genuine bug or issue, please use the Issues section on github: http://github.com/javan/whenever/issues
|
|
103
112
|
|
|
113
|
+
Ryan Bates created a great Railscast about Whenever: http://railscasts.com/episodes/164-cron-in-ruby
|
|
114
|
+
It's a little bit dated now, but remains a good introduction.
|
|
115
|
+
|
|
104
116
|
== License
|
|
105
117
|
|
|
106
118
|
Copyright (c) 2009+ Javan Makhmali
|
data/Rakefile
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
require 'rake'
|
|
3
3
|
|
|
4
|
-
require
|
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/whenever/version")
|
|
5
5
|
|
|
6
6
|
begin
|
|
7
7
|
require 'jeweler'
|
|
8
8
|
Jeweler::Tasks.new do |gemspec|
|
|
9
9
|
gemspec.name = "whenever"
|
|
10
10
|
gemspec.version = Whenever::VERSION
|
|
11
|
-
gemspec.summary = "Clean ruby syntax for
|
|
12
|
-
gemspec.description = "
|
|
11
|
+
gemspec.summary = "Clean ruby syntax for writing and deploying cron jobs."
|
|
12
|
+
gemspec.description = "http://www.allyrics.net/Kid-Cudi/lyrics/Whenever/"
|
|
13
13
|
gemspec.email = "javan@javan.us"
|
|
14
14
|
gemspec.homepage = "http://github.com/javan/whenever"
|
|
15
15
|
gemspec.authors = ["Javan Makhmali"]
|
|
16
|
-
gemspec.add_dependency
|
|
16
|
+
gemspec.add_dependency 'aaronh-chronic', '>= 0.3.9'
|
|
17
|
+
gemspec.add_dependency 'activesupport', '>= 2.3.4'
|
|
18
|
+
gemspec.add_development_dependency 'shoulda', '>= 2.1.1'
|
|
19
|
+
gemspec.add_development_dependency 'mocha', '>= 0.9.5'
|
|
17
20
|
end
|
|
18
21
|
Jeweler::GemcutterTasks.new
|
|
19
22
|
rescue LoadError
|
|
@@ -22,10 +25,10 @@ end
|
|
|
22
25
|
|
|
23
26
|
require 'rake/testtask'
|
|
24
27
|
Rake::TestTask.new(:test) do |test|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
28
|
+
test.libs << 'lib' << 'test'
|
|
29
|
+
test.pattern = 'test/{functional,unit}/**/*_test.rb'
|
|
30
|
+
test.verbose = true
|
|
31
|
+
end
|
|
29
32
|
|
|
30
33
|
task :test => :check_dependencies
|
|
31
34
|
|
data/bin/whenever
CHANGED
|
@@ -4,29 +4,35 @@ require 'rubygems'
|
|
|
4
4
|
require 'optparse'
|
|
5
5
|
require 'whenever'
|
|
6
6
|
|
|
7
|
-
options =
|
|
7
|
+
options = {}
|
|
8
8
|
|
|
9
9
|
OptionParser.new do |opts|
|
|
10
10
|
opts.banner = "Usage: whenever [options]"
|
|
11
|
-
opts.on('-v', '--version') { puts "Whenever v#{Whenever::VERSION}"; exit(0) }
|
|
12
|
-
opts.on('-w', '--write-crontab') { options[:write] = true }
|
|
13
11
|
opts.on('-i', '--update-crontab [identifier]', 'Default: full path to schedule.rb file') do |identifier|
|
|
14
12
|
options[:update] = true
|
|
15
13
|
options[:identifier] = identifier if identifier
|
|
16
14
|
end
|
|
15
|
+
opts.on('-w', '--write-crontab [identifier]', 'Default: full path to schedule.rb file') do |identifier|
|
|
16
|
+
options[:write] = true
|
|
17
|
+
options[:identifier] = identifier if identifier
|
|
18
|
+
end
|
|
17
19
|
opts.on('-c', '--clear-crontab [identifier]') do |identifier|
|
|
18
20
|
options[:clear] = true
|
|
19
21
|
options[:identifier] = identifier if identifier
|
|
20
22
|
end
|
|
23
|
+
opts.on('-s', '--set [variables]', 'Example: --set environment=staging&path=/my/sweet/path') do |set|
|
|
24
|
+
options[:set] = set if set
|
|
25
|
+
end
|
|
21
26
|
opts.on('-f', '--load-file [schedule file]', 'Default: config/schedule.rb') do |file|
|
|
22
27
|
options[:file] = file if file
|
|
23
28
|
end
|
|
24
29
|
opts.on('-u', '--user [user]', 'Default: current user') do |user|
|
|
25
30
|
options[:user] = user if user
|
|
26
31
|
end
|
|
27
|
-
opts.on('-
|
|
28
|
-
options[:
|
|
32
|
+
opts.on('-k', '--cut [lines]', 'Cut lines from the top of the cronfile') do |lines|
|
|
33
|
+
options[:cut] = lines.to_i if lines
|
|
29
34
|
end
|
|
35
|
+
opts.on('-v', '--version') { puts "Whenever v#{Whenever::VERSION}"; exit(0) }
|
|
30
36
|
end.parse!
|
|
31
37
|
|
|
32
38
|
Whenever::CommandLine.execute(options)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Capistrano::Configuration.instance(:must_exist).load do
|
|
2
|
+
|
|
3
|
+
_cset(:whenever_roles) { :db }
|
|
4
|
+
_cset(:whenever_command) { "whenever" }
|
|
5
|
+
_cset(:whenever_identifier) { application }
|
|
6
|
+
_cset(:whenever_update_flags) { "--update-crontab #{whenever_identifier}" }
|
|
7
|
+
_cset(:whenever_clear_flags) { "--clear-crontab #{whenever_identifier}" }
|
|
8
|
+
|
|
9
|
+
# Disable cron jobs at the begining of a deploy.
|
|
10
|
+
after "deploy:update_code", "whenever:clear_crontab"
|
|
11
|
+
# Write the new cron jobs near the end.
|
|
12
|
+
after "deploy:symlink", "whenever:update_crontab"
|
|
13
|
+
# If anything goes wrong, undo.
|
|
14
|
+
after "deploy:rollback", "whenever:update_crontab"
|
|
15
|
+
|
|
16
|
+
namespace :whenever do
|
|
17
|
+
desc "Update application's crontab entries using Whenever"
|
|
18
|
+
task :update_crontab, :roles => whenever_roles do
|
|
19
|
+
# Hack by Jamis to skip a task if the role has no servers defined. http://tinyurl.com/ckjgnz
|
|
20
|
+
next if find_servers_for_task(current_task).empty?
|
|
21
|
+
run "cd #{current_path} && #{whenever_command} #{whenever_update_flags}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
desc "Clear application's crontab entries using Whenever"
|
|
25
|
+
task :clear_crontab, :roles => whenever_roles do
|
|
26
|
+
next if find_servers_for_task(current_task).empty?
|
|
27
|
+
run "cd #{release_path} && #{whenever_command} #{whenever_clear_flags}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
@@ -12,6 +12,7 @@ module Whenever
|
|
|
12
12
|
@options = options
|
|
13
13
|
|
|
14
14
|
@options[:file] ||= 'config/schedule.rb'
|
|
15
|
+
@options[:cut] ||= 0
|
|
15
16
|
@options[:identifier] ||= default_identifier
|
|
16
17
|
|
|
17
18
|
unless File.exists?(@options[:file])
|
|
@@ -23,6 +24,13 @@ module Whenever
|
|
|
23
24
|
warn("[fail] Can only update, write or clear. Choose one.")
|
|
24
25
|
exit(1)
|
|
25
26
|
end
|
|
27
|
+
|
|
28
|
+
unless @options[:cut].to_s =~ /[0-9]*/
|
|
29
|
+
warn("[fail] Can't cut negative lines from the crontab #{options[:cut]}")
|
|
30
|
+
exit(1)
|
|
31
|
+
end
|
|
32
|
+
@options[:cut] = @options[:cut].to_i
|
|
33
|
+
|
|
26
34
|
end
|
|
27
35
|
|
|
28
36
|
def run
|
|
@@ -53,7 +61,7 @@ module Whenever
|
|
|
53
61
|
command << "-u #{@options[:user]}" if @options[:user]
|
|
54
62
|
|
|
55
63
|
command_results = %x[#{command.join(' ')} 2> /dev/null]
|
|
56
|
-
@current_crontab = $?.exitstatus.zero? ? command_results : ''
|
|
64
|
+
@current_crontab = $?.exitstatus.zero? ? prepare(command_results) : ''
|
|
57
65
|
end
|
|
58
66
|
|
|
59
67
|
def write_crontab(contents)
|
|
@@ -77,24 +85,30 @@ module Whenever
|
|
|
77
85
|
end
|
|
78
86
|
end
|
|
79
87
|
|
|
80
|
-
def updated_crontab
|
|
88
|
+
def updated_crontab
|
|
81
89
|
# Check for unopened or unclosed identifier blocks
|
|
82
|
-
if read_crontab.
|
|
90
|
+
if read_crontab =~ Regexp.new("^#{comment_open}$") && (read_crontab =~ Regexp.new("^#{comment_close}$")).nil?
|
|
83
91
|
warn "[fail] Unclosed indentifier; Your crontab file contains '#{comment_open}', but no '#{comment_close}'"
|
|
84
92
|
exit(1)
|
|
85
|
-
elsif
|
|
93
|
+
elsif (read_crontab =~ Regexp.new("^#{comment_open}$")).nil? && read_crontab =~ Regexp.new("^#{comment_close}$")
|
|
86
94
|
warn "[fail] Unopened indentifier; Your crontab file contains '#{comment_close}', but no '#{comment_open}'"
|
|
87
95
|
exit(1)
|
|
88
96
|
end
|
|
89
97
|
|
|
90
98
|
# If an existing identier block is found, replace it with the new cron entries
|
|
91
|
-
if read_crontab.
|
|
92
|
-
|
|
99
|
+
if read_crontab =~ Regexp.new("^#{comment_open}$") && read_crontab =~ Regexp.new("^#{comment_close}$")
|
|
100
|
+
# If the existing crontab file contains backslashes they get lost going through gsub.
|
|
101
|
+
# .gsub('\\', '\\\\\\') preserves them. Go figure.
|
|
102
|
+
read_crontab.gsub(Regexp.new("^#{comment_open}$.+^#{comment_close}$", Regexp::MULTILINE), whenever_cron.chomp.gsub('\\', '\\\\\\'))
|
|
93
103
|
else # Otherwise, append the new cron entries after any existing ones
|
|
94
104
|
[read_crontab, whenever_cron].join("\n\n")
|
|
95
105
|
end
|
|
96
106
|
end
|
|
97
107
|
|
|
108
|
+
def prepare(contents)
|
|
109
|
+
contents.split("\n")[@options[:cut]..-1].join("\n")
|
|
110
|
+
end
|
|
111
|
+
|
|
98
112
|
def comment_base
|
|
99
113
|
"Whenever generated tasks for: #{@options[:identifier]}"
|
|
100
114
|
end
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
module Whenever
|
|
2
2
|
module Output
|
|
3
|
-
|
|
4
3
|
class Cron
|
|
5
4
|
|
|
6
5
|
attr_accessor :time, :task
|
|
7
6
|
|
|
8
|
-
def initialize(time = nil, task = nil, at = nil
|
|
7
|
+
def initialize(time = nil, task = nil, at = nil)
|
|
9
8
|
@time = time
|
|
10
9
|
@task = task
|
|
11
10
|
@at = at.is_a?(String) ? (Chronic.parse(at) || 0) : (at || 0)
|
|
12
|
-
@output_redirection = output_redirection
|
|
13
11
|
end
|
|
14
12
|
|
|
15
13
|
def self.enumerate(item)
|
|
@@ -25,13 +23,13 @@ module Whenever
|
|
|
25
23
|
def self.output(times, job)
|
|
26
24
|
enumerate(times).each do |time|
|
|
27
25
|
enumerate(job.at).each do |at|
|
|
28
|
-
yield new(time, job.output, at
|
|
26
|
+
yield new(time, job.output, at).output
|
|
29
27
|
end
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
30
|
|
|
33
31
|
def output
|
|
34
|
-
[time_in_cron_syntax, task
|
|
32
|
+
[time_in_cron_syntax, task].compact.join(' ').strip
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
def time_in_cron_syntax
|
|
@@ -41,10 +39,6 @@ module Whenever
|
|
|
41
39
|
else parse_time
|
|
42
40
|
end
|
|
43
41
|
end
|
|
44
|
-
|
|
45
|
-
def output_redirection
|
|
46
|
-
OutputRedirection.new(@output_redirection).to_s unless @output_redirection == :not_set
|
|
47
|
-
end
|
|
48
42
|
|
|
49
43
|
protected
|
|
50
44
|
|
|
@@ -60,7 +54,7 @@ module Whenever
|
|
|
60
54
|
end
|
|
61
55
|
|
|
62
56
|
if shortcut
|
|
63
|
-
if @at.is_a?(Time) || (@at.is_a?(Numeric) && @at>0)
|
|
57
|
+
if @at.is_a?(Time) || (@at.is_a?(Numeric) && @at > 0)
|
|
64
58
|
raise ArgumentError, "You cannot specify an ':at' when using the shortcuts for times."
|
|
65
59
|
else
|
|
66
60
|
return shortcut
|
|
@@ -134,6 +128,5 @@ module Whenever
|
|
|
134
128
|
end
|
|
135
129
|
|
|
136
130
|
end
|
|
137
|
-
|
|
138
131
|
end
|
|
139
132
|
end
|
data/lib/whenever/job.rb
CHANGED
|
@@ -1,22 +1,47 @@
|
|
|
1
1
|
module Whenever
|
|
2
2
|
class Job
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
attr_reader :at
|
|
5
5
|
|
|
6
6
|
def initialize(options = {})
|
|
7
7
|
@options = options
|
|
8
|
-
|
|
9
|
-
@
|
|
10
|
-
@
|
|
8
|
+
@at = options.delete(:at)
|
|
9
|
+
@template = options.delete(:template)
|
|
10
|
+
@job_template = options.delete(:job_template) || ":job"
|
|
11
|
+
@options[:output] = Whenever::Output::Redirection.new(options[:output]).to_s if options.has_key?(:output)
|
|
11
12
|
@options[:environment] ||= :production
|
|
12
13
|
@options[:path] ||= Whenever.path
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def output
|
|
16
|
-
@options
|
|
17
|
-
|
|
17
|
+
job = process_template(@template, @options).strip
|
|
18
|
+
process_template(@job_template, { :job => job }).strip
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
protected
|
|
22
|
+
|
|
23
|
+
def process_template(template, options)
|
|
24
|
+
template.gsub(/:\w+/) do |key|
|
|
25
|
+
before_and_after = [$`[-1..-1], $'[0..0]]
|
|
26
|
+
option = options[key.sub(':', '').to_sym]
|
|
27
|
+
|
|
28
|
+
if before_and_after.all? { |c| c == "'" }
|
|
29
|
+
escape_single_quotes(option)
|
|
30
|
+
elsif before_and_after.all? { |c| c == '"' }
|
|
31
|
+
escape_double_quotes(option)
|
|
32
|
+
else
|
|
33
|
+
option
|
|
34
|
+
end
|
|
18
35
|
end
|
|
19
36
|
end
|
|
37
|
+
|
|
38
|
+
def escape_single_quotes(str)
|
|
39
|
+
str.gsub(/'/) { "'\\''" }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def escape_double_quotes(str)
|
|
43
|
+
str.gsub(/"/) { '\"' }
|
|
44
|
+
end
|
|
20
45
|
|
|
21
46
|
end
|
|
22
|
-
end
|
|
47
|
+
end
|
data/lib/whenever/job_list.rb
CHANGED
|
@@ -2,7 +2,7 @@ module Whenever
|
|
|
2
2
|
class JobList
|
|
3
3
|
|
|
4
4
|
def initialize(options)
|
|
5
|
-
@jobs, @env, @set_variables = {}, {}, {}
|
|
5
|
+
@jobs, @env, @set_variables, @pre_set_variables = {}, {}, {}, {}
|
|
6
6
|
|
|
7
7
|
case options
|
|
8
8
|
when String
|
|
@@ -25,7 +25,8 @@ module Whenever
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def set(variable, value)
|
|
28
|
-
|
|
28
|
+
variable = variable.to_sym
|
|
29
|
+
return if @pre_set_variables[variable]
|
|
29
30
|
|
|
30
31
|
instance_variable_set("@#{variable}".to_sym, value)
|
|
31
32
|
self.class.send(:attr_reader, variable.to_sym)
|
|
@@ -59,9 +60,7 @@ module Whenever
|
|
|
59
60
|
end
|
|
60
61
|
end
|
|
61
62
|
|
|
62
|
-
def generate_cron_output
|
|
63
|
-
set_path_environment_variable
|
|
64
|
-
|
|
63
|
+
def generate_cron_output
|
|
65
64
|
[environment_variables, cron_jobs].compact.join
|
|
66
65
|
end
|
|
67
66
|
|
|
@@ -79,22 +78,13 @@ module Whenever
|
|
|
79
78
|
pairs.each do |pair|
|
|
80
79
|
next unless pair.index('=')
|
|
81
80
|
variable, value = *pair.split('=')
|
|
82
|
-
|
|
81
|
+
unless variable.blank? || value.blank?
|
|
82
|
+
variable = variable.strip.to_sym
|
|
83
|
+
set(variable, value.strip)
|
|
84
|
+
@pre_set_variables[variable] = value
|
|
85
|
+
end
|
|
83
86
|
end
|
|
84
87
|
end
|
|
85
|
-
|
|
86
|
-
def set_path_environment_variable
|
|
87
|
-
return if path_should_not_be_set_automatically?
|
|
88
|
-
@env[:PATH] = read_path unless read_path.blank?
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def read_path
|
|
92
|
-
ENV['PATH'] if ENV
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def path_should_not_be_set_automatically?
|
|
96
|
-
@set_path_automatically === false || @env[:PATH] || @env["PATH"]
|
|
97
|
-
end
|
|
98
88
|
|
|
99
89
|
def environment_variables
|
|
100
90
|
return if @env.empty?
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# http://blog.scoutapp.com/articles/2010/09/07/rvm-and-cron-in-production
|
|
2
|
+
set :job_template, "/bin/bash -l -c ':job'"
|
|
3
|
+
|
|
4
|
+
job_type :command, ":task :output"
|
|
5
|
+
job_type :rake, "cd :path && RAILS_ENV=:environment rake :task --silent :output"
|
|
6
|
+
|
|
7
|
+
if File.exists?(File.join(Whenever.path, 'script', 'rails'))
|
|
8
|
+
job_type :runner, "cd :path && script/rails runner -e :environment ':task' :output"
|
|
9
|
+
else
|
|
10
|
+
job_type :runner, "cd :path && script/runner -e :environment ':task' :output"
|
|
11
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Whenever
|
|
2
|
+
module Output
|
|
3
|
+
class Redirection
|
|
4
|
+
|
|
5
|
+
def initialize(output)
|
|
6
|
+
@output = output
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def to_s
|
|
10
|
+
return '' unless defined?(@output)
|
|
11
|
+
case @output
|
|
12
|
+
when String then redirect_from_string
|
|
13
|
+
when Hash then redirect_from_hash
|
|
14
|
+
when NilClass then ">> /dev/null 2>&1"
|
|
15
|
+
else ''
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
protected
|
|
20
|
+
|
|
21
|
+
def stdout
|
|
22
|
+
return unless @output.has_key?(:standard)
|
|
23
|
+
@output[:standard].nil? ? '/dev/null' : @output[:standard]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def stderr
|
|
27
|
+
return unless @output.has_key?(:error)
|
|
28
|
+
@output[:error].nil? ? '/dev/null' : @output[:error]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def redirect_from_hash
|
|
32
|
+
case
|
|
33
|
+
when stdout == '/dev/null' && stderr == '/dev/null'
|
|
34
|
+
"> /dev/null 2>&1"
|
|
35
|
+
when stdout && stderr == '/dev/null'
|
|
36
|
+
">> #{stdout} 2> /dev/null"
|
|
37
|
+
when stdout && stderr
|
|
38
|
+
">> #{stdout} 2>> #{stderr}"
|
|
39
|
+
when stderr == '/dev/null'
|
|
40
|
+
"2> /dev/null"
|
|
41
|
+
when stderr
|
|
42
|
+
"2>> #{stderr}"
|
|
43
|
+
when stdout == '/dev/null'
|
|
44
|
+
"> /dev/null"
|
|
45
|
+
when stdout
|
|
46
|
+
">> #{stdout}"
|
|
47
|
+
else
|
|
48
|
+
''
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def redirect_from_string
|
|
53
|
+
">> #{@output} 2>&1"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/whenever/version.rb
CHANGED
data/lib/whenever.rb
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
require 'chronic'
|
|
2
|
+
require 'active_support/all'
|
|
2
3
|
|
|
3
|
-
# It was previously defined as a dependency of this gem, but that became
|
|
4
|
-
# problematic. See: http://github.com/javan/whenever/issues#issue/1
|
|
5
|
-
begin
|
|
6
|
-
require 'active_support/all'
|
|
7
|
-
rescue LoadError
|
|
8
|
-
warn 'To use Whenever you need the active_support gem:'
|
|
9
|
-
warn '$ gem install activesupport'
|
|
10
|
-
exit(1)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# Whenever files
|
|
14
4
|
require 'whenever/base'
|
|
15
5
|
require 'whenever/job_list'
|
|
16
6
|
require 'whenever/job'
|
|
17
|
-
require 'whenever/
|
|
18
|
-
require 'whenever/
|
|
7
|
+
require 'whenever/cron'
|
|
8
|
+
require 'whenever/output_redirection'
|
|
19
9
|
require 'whenever/command_line'
|
|
20
10
|
require 'whenever/version'
|