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 +4 -4
- data/Gemfile +1 -4
- data/Gemfile.lock +1 -1
- data/README.md +29 -22
- data/lib/schedule_job/cli.rb +19 -10
- data/lib/schedule_job/cron.rb +20 -25
- data/lib/schedule_job/cron_parser.rb +0 -13
- data/lib/schedule_job/version.rb +1 -1
- data/schedule_job.gemspec +1 -1
- metadata +2 -3
- data/lib/schedule_job/cron.treetop +0 -167
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74b687e00b810539cf4895da252bb96bed4d8843265bd07cdd3c3cd3a20960de
|
4
|
+
data.tar.gz: 8f59585f2c14dfd8f7be9496b6ba4db86a43d4e2fcf81405f9d30662fc9b2f60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5650b386a21d969249421e293be7935080c5177feba124497db3ae87f187a6f01529cd145f16548f2b65c66ce674e39cf3f8afa0da8276cd00d3768ab9eeca57
|
7
|
+
data.tar.gz: 7dec6a2da90eba5ab5216dc7bac5e6d6b5644547d96f090c6b5add60c0a0bd01c6f014bda62150f6e9ba4ae1e8c0c867c8da26322888ae709d72e403c40b10df
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
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
|
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 #
|
29
|
-
--every 5h #
|
30
|
-
--every 2d #
|
31
|
-
--every 3M #
|
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" #
|
36
|
-
--cron "0 0/30 8-9 5,20 * ?" #
|
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:
|
43
|
-
2. 2021-11-01
|
44
|
-
3. 2021-11-01 22:
|
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:
|
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:
|
55
|
-
2. 2022-04-01 21:
|
56
|
-
3. 2022-07-01 21:
|
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:
|
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
|
-
|
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:
|
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:
|
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:
|
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
|
data/lib/schedule_job/cli.rb
CHANGED
@@ -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 #
|
38
|
-
--every 5h #
|
39
|
-
--every 2d #
|
40
|
-
--every 3M #
|
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\" #
|
48
|
-
--cron \"0 0/30 8-9 5,20 * ?\" #
|
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
|
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
|
data/lib/schedule_job/cron.rb
CHANGED
@@ -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
|
data/lib/schedule_job/version.rb
CHANGED
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.
|
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.
|
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.
|
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
|