whenever 0.9.7 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +12 -9
- data/Appraisals +19 -0
- data/CHANGELOG.md +33 -1
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +89 -20
- data/bin/whenever +3 -0
- data/bin/wheneverize +5 -2
- data/gemfiles/activesupport4.1.gemfile +3 -1
- data/gemfiles/activesupport4.2.gemfile +3 -1
- data/gemfiles/activesupport5.0.gemfile +7 -0
- data/gemfiles/activesupport5.1.gemfile +7 -0
- data/gemfiles/activesupport5.2.gemfile +7 -0
- data/lib/whenever/capistrano/v2/recipes.rb +3 -2
- data/lib/whenever/capistrano/v3/tasks/whenever.rake +17 -4
- data/lib/whenever/command_line.rb +39 -19
- data/lib/whenever/cron.rb +43 -15
- data/lib/whenever/job.rb +2 -1
- data/lib/whenever/job_list.rb +50 -20
- data/lib/whenever/numeric.rb +1 -1
- data/lib/whenever/setup.rb +4 -0
- data/lib/whenever/version.rb +1 -1
- data/test/functional/command_line_test.rb +159 -32
- data/test/functional/output_at_test.rb +39 -0
- data/test/functional/output_jobs_with_mailto_test.rb +168 -0
- data/test/test_helper.rb +18 -8
- data/test/unit/cron_test.rb +178 -4
- data/test/unit/executable_test.rb +142 -0
- data/whenever.gemspec +1 -0
- metadata +25 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dc5ff14e6e9d357583f5e20d31fafbcf2dfe3aea8ac756cf9103f51504674e9a
|
4
|
+
data.tar.gz: 446e8398b741a1a9a7ee262b3542efb107d1453259083fef03ea50726227d7dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41f396515f594a4726bd9048783653b0b203e0beb4ea65f6b95faf508061d0fd064bec0a31bbcf6dad6a23f68ec4f3364ae6e8f160eb0539ec6073a6c4960242
|
7
|
+
data.tar.gz: 4fbe2b52fc350ee272d7d03638369b8a6443c1ed6e122be511b9ccf07881c1e559d63587153259343febc89db40aa45bc4ca45cf83af885fd618fd5668ddd1d2
|
data/.travis.yml
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
language: ruby
|
2
|
-
script: bundle exec rake
|
3
2
|
|
4
3
|
before_install:
|
5
4
|
- gem install bundler
|
6
|
-
|
5
|
+
- unset _JAVA_OPTIONS
|
7
6
|
rvm:
|
8
|
-
-
|
9
|
-
- 2.
|
10
|
-
- 2.
|
11
|
-
-
|
12
|
-
- 2.3.0
|
13
|
-
- jruby
|
7
|
+
- 2.4.6
|
8
|
+
- 2.5.5
|
9
|
+
- 2.6.3
|
10
|
+
- jruby-9.2.6.0
|
14
11
|
|
15
12
|
gemfile:
|
16
|
-
- Gemfile
|
17
13
|
- gemfiles/activesupport4.1.gemfile
|
18
14
|
- gemfiles/activesupport4.2.gemfile
|
15
|
+
- gemfiles/activesupport5.0.gemfile
|
16
|
+
- gemfiles/activesupport5.1.gemfile
|
17
|
+
- gemfiles/activesupport5.2.gemfile
|
18
|
+
|
19
|
+
env:
|
20
|
+
global:
|
21
|
+
- JRUBY_OPTS=--debug
|
data/Appraisals
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
appraise 'activesupport4.1' do
|
2
|
+
gem "activesupport", "~> 4.1.0"
|
3
|
+
end
|
4
|
+
|
5
|
+
appraise 'activesupport4.2' do
|
6
|
+
gem "activesupport", "~> 4.2.0"
|
7
|
+
end
|
8
|
+
|
9
|
+
appraise 'activesupport5.0' do
|
10
|
+
gem "activesupport", "~> 5.0.0"
|
11
|
+
end
|
12
|
+
|
13
|
+
appraise 'activesupport5.1' do
|
14
|
+
gem "activesupport", "~> 5.1.0"
|
15
|
+
end
|
16
|
+
|
17
|
+
appraise 'activesupport5.2' do
|
18
|
+
gem "activesupport", "~> 5.2.0beta2"
|
19
|
+
end
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,36 @@
|
|
1
|
-
###
|
1
|
+
### unreleased
|
2
|
+
|
3
|
+
### 1.0.0 / Jun 13, 2019
|
4
|
+
|
5
|
+
* First stable release per SemVer.
|
6
|
+
|
7
|
+
* Removes support for versions of Ruby which are no longer supported by the Ruby project.
|
8
|
+
|
9
|
+
### 0.11.0 / April 23, 2019
|
10
|
+
|
11
|
+
* Add support for mapping Range objects to cron range syntax [Tim Craft](https://github.com/javan/whenever/pull/725)
|
12
|
+
|
13
|
+
* Bugfix: Avoid modifying Capistrano `default_env` when setting the whenever environment. [ta1kt0me](https://github.com/javan/whenever/pull/728)
|
14
|
+
|
15
|
+
* Enable to execute whenever's task independently without setting :release_path or :whenever_path [ta1kt0me](https://github.com/javan/whenever/pull/729)
|
16
|
+
|
17
|
+
* Make error message clearer when parsing cron syntax fails due to a trailing space [ignisf](https://github.com/javan/whenever/pull/744)
|
18
|
+
|
19
|
+
### 0.10.0 / November 19, 2017
|
20
|
+
|
21
|
+
* Modify wheneverize to allow for the creating of 'config' directory when not present
|
22
|
+
|
23
|
+
* Add --crontab-command to whenever binary for overriding the crontab command. [Martin Grandrath]
|
24
|
+
|
25
|
+
* Allow setting the path within which Capistrano will execute whenever. [Samuel Johnson](https://github.com/javan/whenever/pull/619)
|
26
|
+
|
27
|
+
* Allow the use of string literals for month and day-of-week in raw cron syntax.. [Potamianos Gregory](https://github.com/javan/whenever/pull/711)
|
28
|
+
|
29
|
+
* Include Capistrano default environment variables when executing Whenever. [Karl Li](https://github.com/javan/whenever/pull/719)
|
30
|
+
|
31
|
+
* Allow configuring an alternative schedule file in Capistrano. [Shinichi Okamoto](https://github.com/javan/whenever/pull/666)
|
32
|
+
|
33
|
+
* Add customizing email recipient option with the MAILTO environment variable. [Chikahiro Tokoro](https://github.com/javan/whenever/pull/678)
|
2
34
|
|
3
35
|
### 0.9.7 / June 14, 2016
|
4
36
|
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -9,7 +9,7 @@ $ gem install whenever
|
|
9
9
|
Or with Bundler in your Gemfile.
|
10
10
|
|
11
11
|
```ruby
|
12
|
-
gem 'whenever', :
|
12
|
+
gem 'whenever', require: false
|
13
13
|
```
|
14
14
|
|
15
15
|
### Getting started
|
@@ -19,7 +19,7 @@ $ cd /apps/my-great-project
|
|
19
19
|
$ wheneverize .
|
20
20
|
```
|
21
21
|
|
22
|
-
This will create an initial `config/schedule.rb` file for you.
|
22
|
+
This will create an initial `config/schedule.rb` file for you (as long as the config folder is already present in your project).
|
23
23
|
|
24
24
|
### The `whenever` command
|
25
25
|
|
@@ -34,28 +34,39 @@ This will simply show you your `schedule.rb` file converted to cron syntax. It d
|
|
34
34
|
$ whenever --update-crontab
|
35
35
|
```
|
36
36
|
|
37
|
+
Other commonly used options include:
|
38
|
+
```sh
|
39
|
+
$ whenever --user app # set a user as which to install the crontab
|
40
|
+
$ whenever --load-file config/my_schedule.rb # set the schedule file
|
41
|
+
$ whenever --crontab-command 'sudo crontab' # override the crontab command
|
42
|
+
```
|
43
|
+
|
37
44
|
You can list installed cron jobs using `crontab -l`.
|
38
45
|
|
39
|
-
Run `whenever --help` for a complete list of options for selecting the schedule to use, setting variables in the schedule,
|
46
|
+
Run `whenever --help` for a complete list of options for selecting the schedule to use, setting variables in the schedule, etc.
|
40
47
|
|
41
48
|
### Example schedule.rb file
|
42
49
|
|
43
50
|
```ruby
|
44
|
-
every 3.hours do
|
51
|
+
every 3.hours do # 1.minute 1.day 1.week 1.month 1.year is also supported
|
45
52
|
runner "MyModel.some_process"
|
46
53
|
rake "my:rake:task"
|
47
54
|
command "/usr/bin/my_great_command"
|
48
55
|
end
|
49
56
|
|
50
|
-
every 1.day, :
|
57
|
+
every 1.day, at: '4:30 am' do
|
51
58
|
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
|
52
59
|
end
|
53
60
|
|
61
|
+
every 1.day, at: ['4:30 am', '6:00 pm'] do
|
62
|
+
runner "Mymodel.task_to_run_in_two_times_every_day"
|
63
|
+
end
|
64
|
+
|
54
65
|
every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
|
55
66
|
runner "SomeModel.ladeeda"
|
56
67
|
end
|
57
68
|
|
58
|
-
every :sunday, :
|
69
|
+
every :sunday, at: '12pm' do # Use any day of the week or :weekend, :weekday
|
59
70
|
runner "Task.do_something_great"
|
60
71
|
end
|
61
72
|
|
@@ -65,7 +76,7 @@ end
|
|
65
76
|
|
66
77
|
# run this task only on servers with the :app role in Capistrano
|
67
78
|
# see Capistrano roles section below
|
68
|
-
every :day, :
|
79
|
+
every :day, at: '12:20am', roles: [:app] do
|
69
80
|
rake "app_server:task"
|
70
81
|
end
|
71
82
|
```
|
@@ -80,7 +91,7 @@ For example:
|
|
80
91
|
job_type :awesome, '/usr/local/bin/awesome :task :fun_level'
|
81
92
|
|
82
93
|
every 2.hours do
|
83
|
-
awesome "party", :
|
94
|
+
awesome "party", fun_level: "extreme"
|
84
95
|
end
|
85
96
|
```
|
86
97
|
|
@@ -113,6 +124,57 @@ Or set the job_template to nil to have your jobs execute normally.
|
|
113
124
|
set :job_template, nil
|
114
125
|
```
|
115
126
|
|
127
|
+
### Parsing dates and times
|
128
|
+
|
129
|
+
Whenever uses the [Chronic](https://github.com/mojombo/chronic) gem to parse the specified dates and times.
|
130
|
+
|
131
|
+
You can set your custom Chronic configuration if the defaults don't fit you.
|
132
|
+
|
133
|
+
For example, to assume a 24 hour clock instead of the default 12 hour clock:
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
set :chronic_options, hours24: true
|
137
|
+
|
138
|
+
# By default this would run the job every day at 3am
|
139
|
+
every 1.day, at: '3:00' do
|
140
|
+
runner "MyModel.nightly_archive_job"
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
You can see a list of all available options here: <https://github.com/mojombo/chronic/blob/master/lib/chronic/parser.rb>
|
145
|
+
|
146
|
+
### Customize email recipient with the `MAILTO` environment variable
|
147
|
+
|
148
|
+
Output from the jobs is sent to the email address configured in the `MAILTO` environment variable.
|
149
|
+
|
150
|
+
There are many ways to further configure the recipient.
|
151
|
+
|
152
|
+
Example: A global configuration, overriding the environment's value:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
env 'MAILTO', 'output_of_cron@example.com'
|
156
|
+
|
157
|
+
every 3.hours do
|
158
|
+
command "/usr/bin/my_great_command"
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
Example: A `MAILTO` configured for all the jobs in an interval block:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
every 3.hours, mailto: 'my_super_command@example.com' do
|
166
|
+
command "/usr/bin/my_super_command"
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
Example: A `MAILTO` configured for a single job:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
every 3.hours do
|
174
|
+
command "/usr/bin/my_super_command", mailto: 'my_super_command_output@example.com'
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
116
178
|
### Capistrano integration
|
117
179
|
|
118
180
|
Use the built-in Capistrano recipe for easy crontab updates with deploys. For Capistrano V3, see the next section.
|
@@ -140,7 +202,7 @@ require "whenever/capistrano"
|
|
140
202
|
|
141
203
|
The capistrano variable `:stage` should be the one holding your environment name. This will make the correct `:environment` available in your `schedule.rb`.
|
142
204
|
|
143
|
-
If both your environments are on the same server you'll want to namespace them or they'll overwrite each other when you deploy:
|
205
|
+
If both your environments are on the same server you'll want to namespace them, or they'll overwrite each other when you deploy:
|
144
206
|
|
145
207
|
```ruby
|
146
208
|
set :whenever_environment, defer { stage }
|
@@ -148,6 +210,13 @@ set :whenever_identifier, defer { "#{application}_#{stage}" }
|
|
148
210
|
require "whenever/capistrano"
|
149
211
|
```
|
150
212
|
|
213
|
+
If you use a schedule at an alternative path, you may configure it like so:
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
set :whenever_load_file, defer { "#{release_path}/somewhere/else/schedule.rb" }
|
217
|
+
require "whenever/capistrano"
|
218
|
+
```
|
219
|
+
|
151
220
|
### Capistrano V3 Integration
|
152
221
|
|
153
222
|
In your "Capfile" file:
|
@@ -172,10 +241,10 @@ different servers in your capistrano deployment, then you can safely stop readin
|
|
172
241
|
now and everything should just work the same way it always has.
|
173
242
|
|
174
243
|
When you define a job in your schedule.rb file, by default it will be deployed to
|
175
|
-
all servers in the whenever_roles list (which defaults to [:db]).
|
244
|
+
all servers in the whenever_roles list (which defaults to `[:db]`).
|
176
245
|
|
177
246
|
However, if you want to restrict certain jobs to only run on subset of servers,
|
178
|
-
you can add a :
|
247
|
+
you can add a `roles: [...]` argument to their definitions. **Make sure to add
|
179
248
|
that role to the whenever_roles list in your deploy.rb.**
|
180
249
|
|
181
250
|
When you run `cap deploy`, jobs with a :roles list specified will only be added to
|
@@ -184,28 +253,28 @@ the crontabs on servers with one or more of the roles in that list.
|
|
184
253
|
Jobs with no :roles argument will be deployed to all servers in the whenever_roles
|
185
254
|
list. This is to maintain backward compatibility with previous releases of whenever.
|
186
255
|
|
187
|
-
So, for example, with the default whenever_roles of [:db]
|
188
|
-
deployed to all servers with the
|
256
|
+
So, for example, with the default whenever_roles of `[:db]`, a job like this would be
|
257
|
+
deployed to all servers with the `:db` role:
|
189
258
|
|
190
259
|
```ruby
|
191
|
-
every :day, :
|
260
|
+
every :day, at: '12:20am' do
|
192
261
|
rake 'foo:bar'
|
193
262
|
end
|
194
263
|
```
|
195
264
|
|
196
|
-
If we set whenever_roles to [:db, :app] in deploy.rb, and have the following
|
265
|
+
If we set whenever_roles to `[:db, :app]` in deploy.rb, and have the following
|
197
266
|
jobs in schedule.rb:
|
198
267
|
|
199
268
|
```ruby
|
200
|
-
every :day, :
|
269
|
+
every :day, at: '1:37pm', roles: [:app] do
|
201
270
|
rake 'app:task' # will only be added to crontabs of :app servers
|
202
271
|
end
|
203
272
|
|
204
|
-
every :hour, :
|
273
|
+
every :hour, roles: [:db] do
|
205
274
|
rake 'db:task' # will only be added to crontabs of :db servers
|
206
275
|
end
|
207
276
|
|
208
|
-
every :day, :
|
277
|
+
every :day, at: '12:02am' do
|
209
278
|
command "run_this_everywhere" # will be deployed to :db and :app servers
|
210
279
|
end
|
211
280
|
```
|
@@ -253,8 +322,8 @@ It's a little bit dated now, but remains a good introduction.
|
|
253
322
|
|
254
323
|
----
|
255
324
|
|
256
|
-
[![Build Status](https://secure.travis-ci.org/javan/whenever.
|
325
|
+
[![Build Status](https://secure.travis-ci.org/javan/whenever.svg)](http://travis-ci.org/javan/whenever)
|
257
326
|
|
258
327
|
----
|
259
328
|
|
260
|
-
Copyright ©
|
329
|
+
Copyright © 2017 Javan Makhmali
|
data/bin/whenever
CHANGED
@@ -35,6 +35,9 @@ OptionParser.new do |opts|
|
|
35
35
|
opts.on('-r', '--roles [role1,role2]', 'Comma-separated list of server roles to generate cron jobs for') do |roles|
|
36
36
|
options[:roles] = roles.split(',').map(&:to_sym) if roles
|
37
37
|
end
|
38
|
+
opts.on('-x', '--crontab-command [command]', 'Default: crontab') do |crontab_command|
|
39
|
+
options[:crontab_command] = crontab_command if crontab_command
|
40
|
+
end
|
38
41
|
opts.on('-v', '--version') { puts "Whenever v#{Whenever::VERSION}"; exit(0) }
|
39
42
|
end.parse!
|
40
43
|
|
data/bin/wheneverize
CHANGED
@@ -58,9 +58,12 @@ if File.exist?(file)
|
|
58
58
|
warn "[skip] `#{file}' already exists"
|
59
59
|
elsif File.exist?(file.downcase)
|
60
60
|
warn "[skip] `#{file.downcase}' exists, which could conflict with `#{file}'"
|
61
|
-
elsif !File.exist?(File.dirname(file))
|
62
|
-
warn "[skip] directory `#{File.dirname(file)}' does not exist"
|
63
61
|
else
|
62
|
+
dir = File.dirname(file)
|
63
|
+
if !File.exist?(dir)
|
64
|
+
warn "[add] creating `#{dir}'"
|
65
|
+
FileUtils.mkdir_p(dir)
|
66
|
+
end
|
64
67
|
puts "[add] writing `#{file}'"
|
65
68
|
File.open(file, "w") { |f| f.write(content) }
|
66
69
|
end
|
@@ -11,6 +11,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
11
11
|
_cset(:whenever_variables) { "environment=#{fetch :whenever_environment}" }
|
12
12
|
_cset(:whenever_update_flags) { "--update-crontab #{fetch :whenever_identifier} --set #{fetch :whenever_variables}" }
|
13
13
|
_cset(:whenever_clear_flags) { "--clear-crontab #{fetch :whenever_identifier}" }
|
14
|
+
_cset(:whenever_path) { fetch :latest_release }
|
14
15
|
|
15
16
|
namespace :whenever do
|
16
17
|
desc "Update application's crontab entries using Whenever"
|
@@ -18,7 +19,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
18
19
|
args = {
|
19
20
|
:command => fetch(:whenever_command),
|
20
21
|
:flags => fetch(:whenever_update_flags),
|
21
|
-
:path => fetch(:
|
22
|
+
:path => fetch(:whenever_path)
|
22
23
|
}
|
23
24
|
|
24
25
|
if whenever_servers.any?
|
@@ -38,7 +39,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
38
39
|
args = {
|
39
40
|
:command => fetch(:whenever_command),
|
40
41
|
:flags => fetch(:whenever_clear_flags),
|
41
|
-
:path => fetch(:
|
42
|
+
:path => fetch(:whenever_path)
|
42
43
|
}
|
43
44
|
|
44
45
|
whenever_run_commands(args)
|
@@ -4,7 +4,7 @@ namespace :whenever do
|
|
4
4
|
|
5
5
|
on roles fetch(:whenever_roles) do |host|
|
6
6
|
args_for_host = block_given? ? args + Array(yield(host)) : args
|
7
|
-
within
|
7
|
+
within fetch(:whenever_path) do
|
8
8
|
with fetch(:whenever_command_environment_variables) do
|
9
9
|
execute(*args_for_host)
|
10
10
|
end
|
@@ -12,17 +12,28 @@ namespace :whenever do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
def load_file
|
16
|
+
file = fetch(:whenever_load_file)
|
17
|
+
if file
|
18
|
+
"-f #{file}"
|
19
|
+
else
|
20
|
+
''
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
15
24
|
desc "Update application's crontab entries using Whenever"
|
16
25
|
task :update_crontab do
|
17
26
|
setup_whenever_task do |host|
|
18
27
|
roles = host.roles_array.join(",")
|
19
|
-
[fetch(:whenever_update_flags),
|
28
|
+
[fetch(:whenever_update_flags), "--roles=#{roles}", load_file]
|
20
29
|
end
|
21
30
|
end
|
22
31
|
|
23
32
|
desc "Clear application's crontab entries using Whenever"
|
24
33
|
task :clear_crontab do
|
25
|
-
setup_whenever_task
|
34
|
+
setup_whenever_task do |host|
|
35
|
+
[fetch(:whenever_clear_flags), load_file]
|
36
|
+
end
|
26
37
|
end
|
27
38
|
|
28
39
|
after "deploy:updated", "whenever:update_crontab"
|
@@ -33,11 +44,13 @@ namespace :load do
|
|
33
44
|
task :defaults do
|
34
45
|
set :whenever_roles, ->{ :db }
|
35
46
|
set :whenever_command, ->{ [:bundle, :exec, :whenever] }
|
36
|
-
set :whenever_command_environment_variables, ->{
|
47
|
+
set :whenever_command_environment_variables, ->{ fetch(:default_env).merge(rails_env: fetch(:whenever_environment)) }
|
37
48
|
set :whenever_identifier, ->{ fetch :application }
|
38
49
|
set :whenever_environment, ->{ fetch :rails_env, fetch(:stage, "production") }
|
39
50
|
set :whenever_variables, ->{ "environment=#{fetch :whenever_environment}" }
|
51
|
+
set :whenever_load_file, ->{ nil }
|
40
52
|
set :whenever_update_flags, ->{ "--update-crontab #{fetch :whenever_identifier} --set #{fetch :whenever_variables}" }
|
41
53
|
set :whenever_clear_flags, ->{ "--clear-crontab #{fetch :whenever_identifier}" }
|
54
|
+
set :whenever_path, ->{ release_path }
|
42
55
|
end
|
43
56
|
end
|
@@ -9,9 +9,10 @@ module Whenever
|
|
9
9
|
def initialize(options={})
|
10
10
|
@options = options
|
11
11
|
|
12
|
-
@options[:
|
13
|
-
@options[:
|
14
|
-
@options[:
|
12
|
+
@options[:crontab_command] ||= 'crontab'
|
13
|
+
@options[:file] ||= 'config/schedule.rb'
|
14
|
+
@options[:cut] ||= 0
|
15
|
+
@options[:identifier] ||= default_identifier
|
15
16
|
|
16
17
|
if !File.exist?(@options[:file]) && @options[:clear].nil?
|
17
18
|
warn("[fail] Can't find file: #{@options[:file]}")
|
@@ -28,6 +29,8 @@ module Whenever
|
|
28
29
|
exit(1)
|
29
30
|
end
|
30
31
|
@options[:cut] = @options[:cut].to_i
|
32
|
+
|
33
|
+
@timestamp = Time.now.to_s
|
31
34
|
end
|
32
35
|
|
33
36
|
def run
|
@@ -55,9 +58,10 @@ module Whenever
|
|
55
58
|
end
|
56
59
|
|
57
60
|
def read_crontab
|
58
|
-
return @current_crontab if
|
61
|
+
return @current_crontab if instance_variable_defined?(:@current_crontab)
|
59
62
|
|
60
|
-
command = [
|
63
|
+
command = [@options[:crontab_command]]
|
64
|
+
command << '-l'
|
61
65
|
command << "-u #{@options[:user]}" if @options[:user]
|
62
66
|
|
63
67
|
command_results = %x[#{command.join(' ')} 2> /dev/null]
|
@@ -65,7 +69,7 @@ module Whenever
|
|
65
69
|
end
|
66
70
|
|
67
71
|
def write_crontab(contents)
|
68
|
-
command = [
|
72
|
+
command = [@options[:crontab_command]]
|
69
73
|
command << "-u #{@options[:user]}" if @options[:user]
|
70
74
|
# Solaris/SmartOS cron does not support the - option to read from stdin.
|
71
75
|
command << "-" unless OS.solaris?
|
@@ -90,19 +94,19 @@ module Whenever
|
|
90
94
|
|
91
95
|
def updated_crontab
|
92
96
|
# Check for unopened or unclosed identifier blocks
|
93
|
-
if read_crontab =~ Regexp.new("^#{
|
94
|
-
warn "[fail] Unclosed indentifier; Your crontab file contains '#{comment_open}', but no '#{comment_close}'"
|
97
|
+
if read_crontab =~ Regexp.new("^#{comment_open_regex}\s*$") && (read_crontab =~ Regexp.new("^#{comment_close_regex}\s*$")).nil?
|
98
|
+
warn "[fail] Unclosed indentifier; Your crontab file contains '#{comment_open(false)}', but no '#{comment_close(false)}'"
|
95
99
|
exit(1)
|
96
|
-
elsif (read_crontab =~ Regexp.new("^#{
|
97
|
-
warn "[fail] Unopened indentifier; Your crontab file contains '#{comment_close}', but no '#{comment_open}'"
|
100
|
+
elsif (read_crontab =~ Regexp.new("^#{comment_open_regex}\s*$")).nil? && read_crontab =~ Regexp.new("^#{comment_close_regex}\s*$")
|
101
|
+
warn "[fail] Unopened indentifier; Your crontab file contains '#{comment_close(false)}', but no '#{comment_open(false)}'"
|
98
102
|
exit(1)
|
99
103
|
end
|
100
104
|
|
101
|
-
# If an existing
|
102
|
-
if read_crontab =~ Regexp.new("^#{
|
105
|
+
# If an existing identifier block is found, replace it with the new cron entries
|
106
|
+
if read_crontab =~ Regexp.new("^#{comment_open_regex}\s*$") && read_crontab =~ Regexp.new("^#{comment_close_regex}\s*$")
|
103
107
|
# If the existing crontab file contains backslashes they get lost going through gsub.
|
104
108
|
# .gsub('\\', '\\\\\\') preserves them. Go figure.
|
105
|
-
read_crontab.gsub(Regexp.new("^#{
|
109
|
+
read_crontab.gsub(Regexp.new("^#{comment_open_regex}\s*$.+^#{comment_close_regex}\s*$", Regexp::MULTILINE), whenever_cron.chomp.gsub('\\', '\\\\\\'))
|
106
110
|
else # Otherwise, append the new cron entries after any existing ones
|
107
111
|
[read_crontab, whenever_cron].join("\n\n")
|
108
112
|
end.gsub(/\n{3,}/, "\n\n") # More than two newlines becomes just two.
|
@@ -120,16 +124,32 @@ module Whenever
|
|
120
124
|
stripped_contents.gsub!(/\s+$/, $/)
|
121
125
|
end
|
122
126
|
|
123
|
-
def comment_base
|
124
|
-
|
127
|
+
def comment_base(include_timestamp = true)
|
128
|
+
if include_timestamp
|
129
|
+
"Whenever generated tasks for: #{@options[:identifier]} at: #{@timestamp}"
|
130
|
+
else
|
131
|
+
"Whenever generated tasks for: #{@options[:identifier]}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def comment_open(include_timestamp = true)
|
136
|
+
"# Begin #{comment_base(include_timestamp)}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def comment_close(include_timestamp = true)
|
140
|
+
"# End #{comment_base(include_timestamp)}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def comment_open_regex
|
144
|
+
"#{comment_open(false)}(#{timestamp_regex}|)"
|
125
145
|
end
|
126
146
|
|
127
|
-
def
|
128
|
-
"#
|
147
|
+
def comment_close_regex
|
148
|
+
"#{comment_close(false)}(#{timestamp_regex}|)"
|
129
149
|
end
|
130
150
|
|
131
|
-
def
|
132
|
-
"
|
151
|
+
def timestamp_regex
|
152
|
+
" at: \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} ([+-]\\d{4}|UTC)"
|
133
153
|
end
|
134
154
|
end
|
135
155
|
end
|