schedule_job 1.0.2 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|