schedule_job 1.0.2 → 1.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11be78ebaf233db44fee63212623c4e68518fa16c1853df6cb87479f7a6733c9
4
- data.tar.gz: a0d22e81142823bc94a5c0c2ee1f69677ffa2bccd536026841308d12bcc1421d
3
+ metadata.gz: 74b687e00b810539cf4895da252bb96bed4d8843265bd07cdd3c3cd3a20960de
4
+ data.tar.gz: 8f59585f2c14dfd8f7be9496b6ba4db86a43d4e2fcf81405f9d30662fc9b2f60
5
5
  SHA512:
6
- metadata.gz: 67070c26ee315c66e29833ca42b5cb2aff986b6f2c40110e30cc0e513e5a3429da8a0e7e7c8ea83c39f67bd0e478f5fe912e6b1e021ae54e981693e0cde9ee47
7
- data.tar.gz: 1598e6c9a1085a9119307c6511aa8886257e2ee617740e66a6e9377ab876899f4c84469ddf26e65395fafab1e59be90154cd1ee49e29701ebf40cff7f2b74ff3
6
+ metadata.gz: 5650b386a21d969249421e293be7935080c5177feba124497db3ae87f187a6f01529cd145f16548f2b65c66ce674e39cf3f8afa0da8276cd00d3768ab9eeca57
7
+ data.tar.gz: 7dec6a2da90eba5ab5216dc7bac5e6d6b5644547d96f090c6b5add60c0a0bd01c6f014bda62150f6e9ba4ae1e8c0c867c8da26322888ae709d72e403c40b10df
data/Gemfile CHANGED
@@ -4,9 +4,6 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  gem "citrus"
7
- # gem "whenever"
8
7
  gem "cronex"
9
8
  gem "parse-cron"
10
- gem "activesupport"
11
- # gem "treetop"
12
- # gem "polyglot"
9
+ gem "activesupport"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- schedule_job (1.0.0)
4
+ schedule_job (1.0.4)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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
@@ -32,20 +32,28 @@ module ScheduleJob
32
32
  options[:crontab_user] = user
33
33
  end
34
34
 
35
- opts.on("-e", "--every DURATION", "Run command every DURATION units of time.
35
+ 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
36
  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
37
+ --every 10m # every 10 minutes
38
+ --every 5h # every 5 hours
39
+ --every 2d # every 2 days
40
+ --every 3M # every 3 months
41
+
42
+ Special durations:
43
+ --every reboot # after every reboot
44
+ --every year # every year
45
+ --every month # every month
46
+ --every week # every week
47
+ --every day # every day
48
+ --every hour # every hour
41
49
  ") do |every|
42
50
  options[:every] = every
43
51
  end
44
52
 
45
53
  opts.on("-c", "--cron CRON", "Run command on the given cron schedule.
46
54
  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
55
+ --cron \"*/5 15 * * 1-5\" # Every 5 minutes, at 3:00 PM, Monday through Friday
56
+ --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
57
  ") do |cron_schedule|
50
58
  options[:cron] = cron_schedule
51
59
  end
@@ -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
@@ -108,7 +94,6 @@ module ScheduleJob
108
94
 
109
95
  def install_cron_job(job)
110
96
  job_spec = job.specification
111
- # puts "Installing new cron job: #{job_spec}"
112
97
 
113
98
  new_crontab = [read_crontab(@user).strip, job_spec.strip].reject(&:empty?).join("\n")
114
99
  new_crontab << "\n" # add a trailing newline
@@ -136,21 +121,12 @@ module ScheduleJob
136
121
  end
137
122
 
138
123
  def write_crontab(new_crontab, user = @user)
124
+ # overwrite crontab interactively, per https://stackoverflow.com/questions/610839/how-can-i-programmatically-create-a-new-cron-job
139
125
  command = ["crontab"]
140
126
  command << "-u #{user}" if user
141
127
  command << "-"
142
128
  command = command.join(" ")
143
129
 
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
130
  stdout, stderr, exit_status = Open3.capture3(command, stdin_data: new_crontab)
155
131
  crontab_output = stdout
156
132
  error_output = stderr
@@ -197,6 +173,25 @@ module ScheduleJob
197
173
  self.new(schedule_spec, command)
198
174
  end
199
175
 
176
+ # duration is one of: reboot, year, month, week, day, hour
177
+ def self.every_simple_duration(duration, command)
178
+ schedule_spec = case duration
179
+ when "reboot"
180
+ "@reboot"
181
+ when "year"
182
+ "@yearly"
183
+ when "month"
184
+ "@monthly"
185
+ when "week"
186
+ "@weekly"
187
+ when "day"
188
+ "@daily"
189
+ when "hour"
190
+ "@hourly"
191
+ end
192
+ self.new(schedule_spec, command)
193
+ end
194
+
200
195
  attr_reader :schedule_spec
201
196
  attr_reader :line_number
202
197
 
@@ -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.4"
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$/).
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.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Ellis
@@ -69,7 +69,6 @@ files:
69
69
  - lib/schedule_job/cli.rb
70
70
  - lib/schedule_job/cron.citrus
71
71
  - lib/schedule_job/cron.rb
72
- - lib/schedule_job/cron.treetop
73
72
  - lib/schedule_job/cron_parser.rb
74
73
  - lib/schedule_job/version.rb
75
74
  - schedule_job.gemspec
@@ -85,7 +84,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
84
  requirements:
86
85
  - - ">="
87
86
  - !ruby/object:Gem::Version
88
- version: 2.7.0
87
+ version: 2.5.0
89
88
  required_rubygems_version: !ruby/object:Gem::Requirement
90
89
  requirements:
91
90
  - - ">="
@@ -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