schedule_job 1.0.2 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11be78ebaf233db44fee63212623c4e68518fa16c1853df6cb87479f7a6733c9
4
- data.tar.gz: a0d22e81142823bc94a5c0c2ee1f69677ffa2bccd536026841308d12bcc1421d
3
+ metadata.gz: 8c49297585195ae17aee50d2b57a41494d54de392821199543822ccfb6c41847
4
+ data.tar.gz: 79ea5e5b3631c2e089ef0e61dd4d11e157ac8763802e2943a8be741fa893b9e5
5
5
  SHA512:
6
- metadata.gz: 67070c26ee315c66e29833ca42b5cb2aff986b6f2c40110e30cc0e513e5a3429da8a0e7e7c8ea83c39f67bd0e478f5fe912e6b1e021ae54e981693e0cde9ee47
7
- data.tar.gz: 1598e6c9a1085a9119307c6511aa8886257e2ee617740e66a6e9377ab876899f4c84469ddf26e65395fafab1e59be90154cd1ee49e29701ebf40cff7f2b74ff3
6
+ metadata.gz: 857fbc0559cf6bd4f6249aa9f8d4e5bc59d7db984aa9541faee46095debb61f115556b2e45e2fddcd7b7706f28fe261d6453de91743d2bce2d9008111290103d
7
+ data.tar.gz: c1a626fe30d047386eb84a8dcffc315f484bd6bba3503f6c5d0ff29de96f7c3fc0a66e22a8adf72247650198c7b5e96bdb31c266589c76d587eabf9fae23ed42
data/Gemfile CHANGED
@@ -2,11 +2,3 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in schedule.gemspec
4
4
  gemspec
5
-
6
- gem "citrus"
7
- # gem "whenever"
8
- gem "cronex"
9
- gem "parse-cron"
10
- gem "activesupport"
11
- # gem "treetop"
12
- # gem "polyglot"
data/Gemfile.lock CHANGED
@@ -1,7 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- schedule_job (1.0.0)
4
+ schedule_job (1.0.6)
5
+ activesupport
6
+ citrus
7
+ cronex
8
+ parse-cron
5
9
 
6
10
  GEM
7
11
  remote: https://rubygems.org/
@@ -22,7 +26,6 @@ GEM
22
26
  concurrent-ruby (~> 1.0)
23
27
  minitest (5.14.4)
24
28
  parse-cron (0.1.4)
25
- rake (13.0.6)
26
29
  rspec (3.10.0)
27
30
  rspec-core (~> 3.10.0)
28
31
  rspec-expectations (~> 3.10.0)
@@ -45,12 +48,7 @@ PLATFORMS
45
48
  x86_64-darwin-18
46
49
 
47
50
  DEPENDENCIES
48
- activesupport
49
51
  bundler
50
- citrus
51
- cronex
52
- parse-cron
53
- rake
54
52
  rspec
55
53
  schedule_job!
56
54
 
data/README.md CHANGED
@@ -17,64 +17,71 @@ Done installing documentation for schedule_job after 0 seconds
17
17
 
18
18
  Example usage:
19
19
  ```
20
- ~ ❯ schedule -h
20
+ ~ ❯ schedule --help
21
21
  Usage: schedule [options] command
22
22
  -d, --dryrun Report what would happen but do not install the scheduled job.
23
23
  -l, --list List installed cron jobs.
24
24
  -r, --rm JOB_ID Remove the specified job id as indicated by --list
25
25
  -u, --user USER User that the crontab belongs to.
26
- -e, --every DURATION Run command every DURATION units of time.
26
+ -e, --every DURATION Run command every DURATION units of time (valid suffixes are m, h, d, M). DURATION may also be one of the special keywords: reboot, year, month, week, day, hour
27
27
  For example:
28
- --every 10m # meaning, every 10 minutes
29
- --every 5h # meaning, every 5 hours
30
- --every 2d # meaning, every 2 days
31
- --every 3M # meaning, every 3 months
28
+ --every 10m # every 10 minutes
29
+ --every 5h # every 5 hours
30
+ --every 2d # every 2 days
31
+ --every 3M # every 3 months
32
+
33
+ Special durations:
34
+ --every reboot # after every reboot
35
+ --every year # every year
36
+ --every month # every month
37
+ --every week # every week
38
+ --every day # every day
39
+ --every hour # every hour
32
40
 
33
41
  -c, --cron CRON Run command on the given cron schedule.
34
42
  For example:
35
- --cron "*/5 15 * * 1-5" # meaning, Every 5 minutes, at 3:00 PM, Monday through Friday
36
- --cron "0 0/30 8-9 5,20 * ?" # meaning, Every 30 minutes, between 8:00 AM and 9:59 AM, on day 5 and 20 of the month
43
+ --cron "*/5 15 * * 1-5" # Every 5 minutes, at 3:00 PM, Monday through Friday
44
+ --cron "0 0/30 8-9 5,20 * ?" # Every 30 minutes, between 8:00 AM and 9:59 AM, on day 5 and 20 of the month
37
45
 
38
46
  ~ ❯ schedule -l
39
47
  ~ ❯ schedule -d -e 10m backup.sh
40
48
  Scheduling: backup.sh Every 10 minutes
41
49
  Next three runs:
42
- 1. 2021-11-01 21:40:00 -0500
43
- 2. 2021-11-01 21:50:00 -0500
44
- 3. 2021-11-01 22:00:00 -0500
50
+ 1. 2021-11-01 21:50:00 -0500
51
+ 2. 2021-11-01 22:00:00 -0500
52
+ 3. 2021-11-01 22:10:00 -0500
45
53
  ~ ❯ schedule -l
46
54
  Jobs
47
55
  1. backup.sh Every 10 minutes
48
56
  ~ ❯ crontab -l
49
57
  */10 * * * * backup.sh
50
-
51
58
  ~ ❯ schedule -e 3M quarterly_backup.sh
52
- Scheduling: quarterly_backup.sh At 9:43 PM, on day 1 of the month, every 3 months
59
+ Scheduling: quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
53
60
  Next three runs:
54
- 1. 2022-01-01 21:43:00 -0600
55
- 2. 2022-04-01 21:43:00 -0500
56
- 3. 2022-07-01 21:43:00 -0500
61
+ 1. 2022-01-01 21:50:00 -0600
62
+ 2. 2022-04-01 21:50:00 -0500
63
+ 3. 2022-07-01 21:50:00 -0500
57
64
  ~ ❯ schedule -l
58
65
  Jobs
59
66
  1. backup.sh Every 10 minutes
60
- 2. quarterly_backup.sh At 9:43 PM, on day 1 of the month, every 3 months
67
+ 2. quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
61
68
  ~ ❯ crontab -l
62
69
  */10 * * * * backup.sh
63
- 43 21 1 */3 * quarterly_backup.sh
64
-
70
+ 50 21 1 */3 * quarterly_backup.sh
65
71
  ~ ❯ schedule --dryrun --rm 1
66
72
  Would remove: backup.sh Every 10 minutes
67
73
  ~ ❯ schedule --dryrun --rm 2
68
- Would remove: quarterly_backup.sh At 9:43 PM, on day 1 of the month, every 3 months
74
+ Would remove: quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
69
75
  ~ ❯ schedule --rm 1
70
76
  Removing: backup.sh Every 10 minutes
71
77
  ~ ❯ schedule -l
72
78
  Jobs
73
- 1. quarterly_backup.sh At 9:43 PM, on day 1 of the month, every 3 months
79
+ 1. quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
74
80
  ~ ❯ schedule --rm 1
75
- Removing: quarterly_backup.sh At 9:43 PM, on day 1 of the month, every 3 months
81
+ Removing: quarterly_backup.sh At 9:50 PM, on day 1 of the month, every 3 months
76
82
  ~ ❯ schedule -l
77
83
  ~ ❯ crontab -l
84
+ ~ ❯
78
85
  ```
79
86
 
80
87
  ## License
@@ -1,7 +1,5 @@
1
1
  require "optparse"
2
2
 
3
- # schedule --every 10m "my_command --foo --bar"
4
-
5
3
  module ScheduleJob
6
4
  class Cli
7
5
  def self.run(argv = ARGV)
@@ -32,20 +30,28 @@ module ScheduleJob
32
30
  options[:crontab_user] = user
33
31
  end
34
32
 
35
- opts.on("-e", "--every DURATION", "Run command every DURATION units of time.
33
+ opts.on("-e", "--every DURATION", "Run command every DURATION units of time (valid suffixes are m, h, d, M). DURATION may also be one of the special keywords: reboot, year, month, week, day, hour
36
34
  For example:
37
- --every 10m # meaning, every 10 minutes
38
- --every 5h # meaning, every 5 hours
39
- --every 2d # meaning, every 2 days
40
- --every 3M # meaning, every 3 months
35
+ --every 10m # every 10 minutes
36
+ --every 5h # every 5 hours
37
+ --every 2d # every 2 days
38
+ --every 3M # every 3 months
39
+
40
+ Special durations:
41
+ --every reboot # after every reboot
42
+ --every year # every year
43
+ --every month # every month
44
+ --every week # every week
45
+ --every day # every day
46
+ --every hour # every hour
41
47
  ") do |every|
42
48
  options[:every] = every
43
49
  end
44
50
 
45
51
  opts.on("-c", "--cron CRON", "Run command on the given cron schedule.
46
52
  For example:
47
- --cron \"*/5 15 * * 1-5\" # meaning, Every 5 minutes, at 3:00 PM, Monday through Friday
48
- --cron \"0 0/30 8-9 5,20 * ?\" # meaning, Every 30 minutes, between 8:00 AM and 9:59 AM, on day 5 and 20 of the month
53
+ --cron \"*/5 15 * * 1-5\" # Every 5 minutes, at 3:00 PM, Monday through Friday
54
+ --cron \"0 0/30 8-9 5,20 * ?\" # Every 30 minutes, between 8:00 AM and 9:59 AM, on day 5 and 20 of the month
49
55
  ") do |cron_schedule|
50
56
  options[:cron] = cron_schedule
51
57
  end
@@ -63,6 +69,8 @@ module ScheduleJob
63
69
  remove_job(args)
64
70
  when args[:cron] || args[:every] # write jobs
65
71
  install_job(args)
72
+ else
73
+ puts "No parameters specified. Please specify one of: --every, --cron, --list, or --rm"
66
74
  end
67
75
  end
68
76
 
@@ -90,13 +98,14 @@ module ScheduleJob
90
98
  Cron::Job.new(cron_schedule, command)
91
99
  when args[:every]
92
100
  duration = args[:every]
93
- match = duration.match(/(\d+)(m|h|d|M)/)
94
- if match
101
+ if match = duration.match(/(\d+)(m|h|d|M)/)
95
102
  qty = match[1].to_i
96
103
  unit_of_time = match[2].to_s
97
104
  Cron::Job.every(qty, unit_of_time, command)
105
+ elsif duration.match(/reboot|year|month|week|day|hour/)
106
+ Cron::Job.every_simple_duration(duration, command)
98
107
  else
99
- puts "'#{duration}' is an invalid duration. The duration must be specified as: integer followed immediately by m (minutes), h (hours), d (days), M (months) (e.g. 10m)"
108
+ puts "'#{duration}' is an invalid duration. The duration must be specified as either (1) integer followed immediately by m (minutes), h (hours), d (days), M (months) (e.g. 10m) or (2) reboot, year, month, week, day, hour"
100
109
  exit(1)
101
110
  end
102
111
  end
@@ -50,12 +50,6 @@ module ScheduleJob
50
50
 
51
51
  raise("Unable to read crontab: #{error_output}") if !exit_status.success? && !no_crontab
52
52
 
53
- # puts "read_crontab()"
54
- # puts "stdout:"
55
- # puts stdout
56
- # puts "stderr:"
57
- # puts stderr
58
-
59
53
  crontab_output
60
54
  end
61
55
 
@@ -63,16 +57,8 @@ module ScheduleJob
63
57
  def parse_crontab(user_crontab)
64
58
  parser = TableParser.new(user_crontab)
65
59
 
66
- # user_crontab.each_line do |line|
67
- # puts line
68
- # puts "valid? #{LineParser.valid?(line)}"
69
- # puts LineParser.parse(line)
70
- # end
71
-
72
60
  return [], [] unless parser.valid?
73
61
 
74
- # puts "valid!"
75
-
76
62
  environment_vars = parser.environment_vars&.map do |env_directive|
77
63
  name = env_directive[:var].to_s
78
64
  expr = env_directive[:expr].to_s
@@ -96,19 +82,22 @@ module ScheduleJob
96
82
  puts "Scheduling: #{job.to_s}"
97
83
  install_cron_job(job)
98
84
  end
99
- puts "Next three runs:"
100
- cron_parser = CronParser.new(job.schedule_spec)
101
- first_run_time = cron_parser.next(Time.now)
102
- second_run_time = cron_parser.next(first_run_time)
103
- third_run_time = cron_parser.next(second_run_time)
104
- puts "1. #{first_run_time}"
105
- puts "2. #{second_run_time}"
106
- puts "3. #{third_run_time}"
85
+
86
+ cron_parser = CronParser.new(job.schedule_spec) rescue nil
87
+ if cron_parser
88
+ puts "Next three runs:"
89
+ first_run_time = cron_parser.next(Time.now)
90
+ second_run_time = cron_parser.next(first_run_time)
91
+ third_run_time = cron_parser.next(second_run_time)
92
+
93
+ puts "1. #{first_run_time}"
94
+ puts "2. #{second_run_time}"
95
+ puts "3. #{third_run_time}"
96
+ end
107
97
  end
108
98
 
109
99
  def install_cron_job(job)
110
100
  job_spec = job.specification
111
- # puts "Installing new cron job: #{job_spec}"
112
101
 
113
102
  new_crontab = [read_crontab(@user).strip, job_spec.strip].reject(&:empty?).join("\n")
114
103
  new_crontab << "\n" # add a trailing newline
@@ -136,21 +125,12 @@ module ScheduleJob
136
125
  end
137
126
 
138
127
  def write_crontab(new_crontab, user = @user)
128
+ # overwrite crontab interactively, per https://stackoverflow.com/questions/610839/how-can-i-programmatically-create-a-new-cron-job
139
129
  command = ["crontab"]
140
130
  command << "-u #{user}" if user
141
131
  command << "-"
142
132
  command = command.join(" ")
143
133
 
144
- # command = "(crontab -l ; echo \"#{job_spec}\") | crontab -" # add new job to bottom of crontab, per https://stackoverflow.com/questions/610839/how-can-i-programmatically-create-a-new-cron-job
145
- # puts "writing new crontab:"
146
- # puts new_crontab
147
- # puts "*" * 80
148
-
149
- # puts "write_crontab:"
150
- # puts "command: #{command}"
151
- # puts "new crontab:"
152
- # puts new_crontab
153
-
154
134
  stdout, stderr, exit_status = Open3.capture3(command, stdin_data: new_crontab)
155
135
  crontab_output = stdout
156
136
  error_output = stderr
@@ -185,14 +165,33 @@ module ScheduleJob
185
165
  hour = next_moment.hour
186
166
  day = next_moment.day
187
167
  schedule_spec = case duration_unit_of_time
188
- when "m"
189
- "*/#{duration_quantity} * * * *"
190
- when "h"
191
- "#{minute} */#{duration_quantity} * * *"
192
- when "d"
193
- "#{minute} #{hour} */#{duration_quantity} * *"
194
- when "M"
195
- "#{minute} #{hour} #{day} */#{duration_quantity} *"
168
+ when "m"
169
+ "*/#{duration_quantity} * * * *"
170
+ when "h"
171
+ "#{minute} */#{duration_quantity} * * *"
172
+ when "d"
173
+ "#{minute} #{hour} */#{duration_quantity} * *"
174
+ when "M"
175
+ "#{minute} #{hour} #{day} */#{duration_quantity} *"
176
+ end
177
+ self.new(schedule_spec, command)
178
+ end
179
+
180
+ # duration is one of: reboot, year, month, week, day, hour
181
+ def self.every_simple_duration(duration, command)
182
+ schedule_spec = case duration
183
+ when "reboot"
184
+ "@reboot"
185
+ when "year"
186
+ "@yearly"
187
+ when "month"
188
+ "@monthly"
189
+ when "week"
190
+ "@weekly"
191
+ when "day"
192
+ "@daily"
193
+ when "hour"
194
+ "@hourly"
196
195
  end
197
196
  self.new(schedule_spec, command)
198
197
  end
@@ -223,7 +222,23 @@ module ScheduleJob
223
222
  end
224
223
 
225
224
  def to_s
226
- schedule = Cronex::ExpressionDescriptor.new(@schedule_spec).description
225
+ schedule = case @schedule_spec
226
+ when "@reboot"
227
+ "at every reboot"
228
+ when "@yearly", "@annually"
229
+ "every year"
230
+ when "@monthly"
231
+ "every month"
232
+ when "@weekly"
233
+ "every week"
234
+ when "@daily"
235
+ "every day"
236
+ when "@hourly"
237
+ "every hour"
238
+ else
239
+ Cronex::ExpressionDescriptor.new(@schedule_spec).description
240
+ end
241
+
227
242
  # str = "#{@command} #{schedule} (line #{@line_number}, pos #{@pos_offset})"
228
243
  str = "#{@command} #{schedule}"
229
244
  end
@@ -17,10 +17,6 @@ end
17
17
 
18
18
  Citrus.require("schedule_job/cron")
19
19
 
20
- # require "polyglot"
21
- # require "treetop"
22
- # require "schedule_job/cron.treetop"
23
-
24
20
  module ScheduleJob
25
21
  module Cron
26
22
  Grammar = ScheduleCronParser
@@ -34,7 +30,6 @@ module ScheduleJob
34
30
 
35
31
  def self.parse(user_crontab_string)
36
32
  Grammar.parse(user_crontab_string, root: :user_crontab)
37
- # ::CrontabParser.new.parse(user_crontab_string, root: :user_crontab)
38
33
  end
39
34
 
40
35
  def initialize(user_crontab_string)
@@ -55,17 +50,10 @@ module ScheduleJob
55
50
 
56
51
  def environment_vars
57
52
  @user_crontab&.capture(:environment)&.captures(:directive)
58
- # puts @user_crontab.methods.sort.inspect
59
- # puts @user_crontab.inspect
60
- # puts "*" * 80
61
- # puts @user_crontab.environment_spec.inspect
62
- # exit()
63
- # @user_crontab&.environment&.directive
64
53
  end
65
54
 
66
55
  def job_specs
67
56
  @user_crontab&.capture(:jobspecs)&.captures(:jobspec)
68
- # @user_crontab&.jobspecs&.jobspec
69
57
  end
70
58
  end
71
59
 
@@ -78,7 +66,6 @@ module ScheduleJob
78
66
 
79
67
  def self.parse(cron_line)
80
68
  Grammar.parse(cron_line, root: :jobspec, consume: false)
81
- # ::CrontabParser.new.parse(cron_line, root: :jobspec, consume_all_input: false)
82
69
  end
83
70
  end
84
71
  end
@@ -1,3 +1,3 @@
1
1
  module ScheduleJob
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.7"
3
3
  end
data/schedule_job.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.description = "job scheduler"
11
11
  spec.homepage = "https://github.com/davidkellis/scheduler"
12
12
  spec.license = "MIT"
13
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
14
14
 
15
15
  spec.files = Dir["**/**"].
16
16
  grep_v(/.gem$/).
@@ -20,6 +20,10 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  spec.add_development_dependency "bundler"
23
- spec.add_development_dependency "rake"
24
23
  spec.add_development_dependency "rspec"
24
+
25
+ spec.add_dependency "citrus"
26
+ spec.add_dependency "cronex"
27
+ spec.add_dependency "parse-cron"
28
+ spec.add_dependency "activesupport"
25
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schedule_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Ellis
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,13 +39,55 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: citrus
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
- type: :development
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cronex
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: parse-cron
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
49
91
  prerelease: false
50
92
  version_requirements: !ruby/object:Gem::Requirement
51
93
  requirements:
@@ -69,7 +111,6 @@ files:
69
111
  - lib/schedule_job/cli.rb
70
112
  - lib/schedule_job/cron.citrus
71
113
  - lib/schedule_job/cron.rb
72
- - lib/schedule_job/cron.treetop
73
114
  - lib/schedule_job/cron_parser.rb
74
115
  - lib/schedule_job/version.rb
75
116
  - schedule_job.gemspec
@@ -85,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
126
  requirements:
86
127
  - - ">="
87
128
  - !ruby/object:Gem::Version
88
- version: 2.7.0
129
+ version: 2.5.0
89
130
  required_rubygems_version: !ruby/object:Gem::Requirement
90
131
  requirements:
91
132
  - - ">="
@@ -1,167 +0,0 @@
1
- grammar Crontab
2
- rule user_crontab
3
- sep?
4
- environment_spec:(environment sep)?
5
- jobspecs?
6
- sep?
7
- end
8
-
9
- rule environment
10
- head:directive tail:(sep directive)*
11
- end
12
-
13
- rule directive
14
- var space "=" space expr
15
- end
16
-
17
- rule var
18
- alpha alphanumeric?
19
- end
20
-
21
- rule expr
22
- command
23
- end
24
-
25
- rule jobspecs
26
- head:jobspec tail:(sep jobspec)*
27
- end
28
-
29
- rule jobspec
30
- schedule_spec space command ws*
31
- end
32
-
33
- rule schedule_spec
34
- standard / special
35
- end
36
-
37
- rule standard
38
- minute space hour space dayofmonth space month space dayofweek
39
- end
40
-
41
- rule special
42
- "@" ("yearly" / "annually" / "monthly" / "weekly" / "daily" / "hourly" / "reboot")
43
- end
44
-
45
- rule minute
46
- step
47
- end
48
-
49
- rule hour
50
- step
51
- end
52
-
53
- rule dayofmonthtypes
54
- step
55
- end
56
-
57
- rule monthtypes
58
- step / altmonths
59
- end
60
-
61
- rule dayofweektypes
62
- step / altdays
63
- end
64
-
65
- rule dayofmonth
66
- dayofmonthtypes ("," dayofmonthtypes)*
67
- end
68
-
69
- rule month
70
- monthtypes ("," monthtypes)*
71
- end
72
-
73
- rule dayofweek
74
- dayofweektypes ("," dayofweektypes)*
75
- end
76
-
77
- rule command
78
- quoted_string
79
- / (!("\n" / comment) .)+
80
- end
81
-
82
- rule step
83
- common ("/" int)?
84
- end
85
-
86
- rule common
87
- range / int / any
88
- end
89
-
90
- rule range
91
- int "-" int
92
- end
93
-
94
- rule altdays
95
- days ("," days)*
96
- end
97
-
98
- rule altmonths
99
- months ("," months)*
100
- end
101
-
102
- rule days
103
- "MON" / "TUE" / "WED" / "THU" / "FRI" / "SAT" / "SUN"
104
- end
105
-
106
- rule months
107
- "JAN" / "FEB" / "MAR" / "APR" / "MAY" / "JUN" / "JUL" / "AUG" / "SEP" / "OCT" / "NOV" / "DEC"
108
- end
109
-
110
- rule any
111
- "*"
112
- end
113
-
114
- rule int
115
- [0-9]+
116
- end
117
-
118
- rule alpha
119
- [a-zA-Z]+
120
- end
121
-
122
- rule alphanumeric
123
- [a-zA-Z0-9]+
124
- end
125
-
126
- rule sep
127
- (ws* nl)+
128
- end
129
-
130
- rule ws
131
- space / comment
132
- end
133
-
134
- rule space
135
- [ \t]+
136
- end
137
-
138
- rule nl
139
- [\n]+
140
- end
141
-
142
- rule comment
143
- "#" (!"\n" .)*
144
- end
145
-
146
- rule quoted_string
147
- "\"" ( (!("\"" / "\\") .) / escape)* "\""
148
- / "'" ( (!("'" / "\\") .) / escape)* "'"
149
- end
150
-
151
- rule escape
152
- "\\" escape_sequence
153
- end
154
-
155
- rule escape_sequence
156
- "'"
157
- / "\""
158
- / "\\"
159
- / "b"
160
- / "f"
161
- / "n"
162
- / "r"
163
- / "t"
164
- / "v"
165
- end
166
-
167
- end