cron_wrapper 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +1 -1
- data/Rakefile +1 -1
- data/cron_wrapper.gemspec +4 -6
- data/lib/cron/awesome_script.rb +1 -0
- data/lib/cron_wrapper.rb +40 -11
- data/spec/cron_wrapper_spec.rb +150 -28
- metadata +7 -28
- data.tar.gz.sig +0 -0
- data/lib/cron/foo.rb +0 -1
- metadata.gz.sig +0 -0
data/Manifest
CHANGED
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('cron_wrapper', '0.0.
|
5
|
+
Echoe.new('cron_wrapper', '0.0.9') do |p|
|
6
6
|
p.description = "A gem that provides useful features for running ruby or Rails scripts with cron"
|
7
7
|
p.url = "http://rubyisbeautiful.com"
|
8
8
|
p.author = "Bryan Taylor"
|
data/cron_wrapper.gemspec
CHANGED
@@ -2,24 +2,22 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{cron_wrapper}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.9"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Bryan Taylor"]
|
9
|
-
s.
|
10
|
-
s.date = %q{2011-02-22}
|
9
|
+
s.date = %q{2011-03-02}
|
11
10
|
s.default_executable = %q{cron_wrapper}
|
12
11
|
s.description = %q{A gem that provides useful features for running ruby or Rails scripts with cron}
|
13
12
|
s.email = %q{btaylor39 @nospam@ csc.com}
|
14
13
|
s.executables = ["cron_wrapper"]
|
15
|
-
s.extra_rdoc_files = ["bin/cron_wrapper", "lib/cron/
|
16
|
-
s.files = ["Manifest", "Rakefile", "bin/cron_wrapper", "cron_wrapper.gemspec", "lib/cron/
|
14
|
+
s.extra_rdoc_files = ["bin/cron_wrapper", "lib/cron/awesome_script.rb", "lib/cron_wrapper.rb"]
|
15
|
+
s.files = ["Manifest", "Rakefile", "bin/cron_wrapper", "cron_wrapper.gemspec", "lib/cron/awesome_script.rb", "lib/cron_wrapper.rb", "spec/cron_wrapper_spec.rb", "spec/spec_helper.rb"]
|
17
16
|
s.homepage = %q{http://rubyisbeautiful.com}
|
18
17
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cron_wrapper"]
|
19
18
|
s.require_paths = ["lib"]
|
20
19
|
s.rubyforge_project = %q{cron_wrapper}
|
21
20
|
s.rubygems_version = %q{1.3.7}
|
22
|
-
s.signing_key = %q{/Users/bryan/.gem/gem-private_key.pem}
|
23
21
|
s.summary = %q{features: locking to prevent resource contention, standard logging, optional rails integration}
|
24
22
|
|
25
23
|
if s.respond_to? :specification_version then
|
@@ -0,0 +1 @@
|
|
1
|
+
sleep(2); puts "awesome"
|
data/lib/cron_wrapper.rb
CHANGED
@@ -17,6 +17,7 @@ class CronWrapper
|
|
17
17
|
@options[:verbose] = false
|
18
18
|
@options[:log] = nil
|
19
19
|
@options[:target] = nil
|
20
|
+
@options[:extra] = nil
|
20
21
|
|
21
22
|
@others = []
|
22
23
|
|
@@ -47,11 +48,7 @@ class CronWrapper
|
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
|
51
|
-
foo.order!
|
52
|
-
rescue OptionParser::InvalidOption => e
|
53
|
-
@others << e.args
|
54
|
-
end
|
51
|
+
@others = foo.order!
|
55
52
|
|
56
53
|
# if they did not enter a script name, then give them usage
|
57
54
|
if @options[:target].nil? or @options[:target] == ''
|
@@ -111,18 +108,50 @@ class CronWrapper
|
|
111
108
|
lock_file = File.join(@options[:lock_dir], "/#{base_name}.lock")
|
112
109
|
|
113
110
|
if File.exists? lock_file
|
111
|
+
stale = false
|
114
112
|
lock_pid = File.read(lock_file)
|
115
|
-
ps_output =
|
116
|
-
|
113
|
+
ps_output = nil
|
114
|
+
|
115
|
+
unless lock_pid =~ /\d+/
|
116
|
+
stale = true
|
117
|
+
end
|
118
|
+
|
119
|
+
unless stale
|
120
|
+
begin
|
121
|
+
ps_output = `ps -p #{lock_pid}`
|
122
|
+
rescue
|
123
|
+
logger.debug "ps failed, assuming stale"
|
124
|
+
stale = true
|
125
|
+
end
|
126
|
+
|
127
|
+
if ps_output.split("\n").length < 1
|
128
|
+
logger.debug "no ps output for pid #{lock_pid}, assuming stale"
|
129
|
+
stale = true
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
if stale
|
134
|
+
logger.debug "cleaning stale pid #{lock_pid} from #{lock_file}"
|
135
|
+
FileUtils.rm_f lock_file
|
136
|
+
else
|
117
137
|
logger.debug "#{base_name} is already running, skipping"
|
118
138
|
exit
|
119
|
-
else
|
120
|
-
logger.debug "cleaning stale pid #{lock_pid} from #{lock_file}"
|
121
139
|
end
|
140
|
+
else
|
141
|
+
logger.debug "there was no lock file"
|
122
142
|
end
|
123
143
|
|
124
|
-
|
125
|
-
|
144
|
+
begin
|
145
|
+
pid = Process::pid
|
146
|
+
File.open(lock_file, 'w') do |file|
|
147
|
+
file << pid
|
148
|
+
end
|
149
|
+
logger.debug "wrote new pid #{pid} to lock file"
|
150
|
+
rescue => e
|
151
|
+
logger.debug "got an error writing to lock file"
|
152
|
+
logger.info e.message
|
153
|
+
logger.debug e.backtrace
|
154
|
+
exit
|
126
155
|
end
|
127
156
|
|
128
157
|
|
data/spec/cron_wrapper_spec.rb
CHANGED
@@ -7,6 +7,10 @@ def remove_lock
|
|
7
7
|
FileUtils.rm_f "tmp/locks/awesome_script.lock" rescue nil
|
8
8
|
end
|
9
9
|
|
10
|
+
def remove_log
|
11
|
+
FileUtils.rm_f "log/awesome_script.log" rescue nil
|
12
|
+
end
|
13
|
+
|
10
14
|
|
11
15
|
describe "cron_wrapper" do
|
12
16
|
|
@@ -15,56 +19,174 @@ describe "cron_wrapper" do
|
|
15
19
|
FileUtils.mkdir_p "#{root}/log"
|
16
20
|
FileUtils.mkdir_p "#{root}/lib/cron"
|
17
21
|
File.open("#{root}/lib/cron/awesome_script.rb", 'w') do |file|
|
18
|
-
file. << 'sleep(
|
22
|
+
file. << 'sleep(2); puts "awesome"'
|
19
23
|
end
|
20
24
|
end
|
21
25
|
|
22
26
|
before(:each) do
|
23
27
|
@pid = nil
|
24
|
-
|
28
|
+
remove_log
|
25
29
|
end
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
describe "rails" do
|
32
|
+
|
33
|
+
before(:all) do
|
34
|
+
FileUtils.mkdir_p "config"
|
35
|
+
|
36
|
+
File.open("#{root}/config/environment.rb", 'w') do |file|
|
37
|
+
file << "class Rails; def self.root; return '#{root}'; end; end;"
|
38
|
+
end
|
39
|
+
|
40
|
+
File.open("#{root}/lib/cron/rails_script.rb", 'w') do |file|
|
41
|
+
file << "str = Rails.root rescue 'no'; File.open('#{root}/tmp/result', 'w'){ |file| file << str }"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
after(:each) do
|
46
|
+
FileUtils.rm_rf("tmp/result") rescue nil
|
47
|
+
end
|
48
|
+
|
49
|
+
after(:all) do
|
50
|
+
FileUtils.rm_rf("#{root}/lib/cron/rails_script.rb")
|
51
|
+
FileUtils.rm_rf("#{root}/config/environment.rb")
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
it "should not load rails if not passed on the commandline" do
|
56
|
+
t = Thread.new { `#{cmd} --wrap rails_script --wrap-verbose --wrap-root #{root} --wrap-log log/rails_script.log` }
|
57
|
+
t.join
|
58
|
+
File.read("tmp/result").should == "no"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should load rails if passed on the commandline" do
|
62
|
+
t = Thread.new { `#{cmd} --wrap-rails --wrap rails_script --wrap-verbose --wrap-root #{root} --wrap-log log/rails_script.log` }
|
63
|
+
t.join
|
64
|
+
File.read("tmp/result").should == root
|
65
|
+
end
|
31
66
|
end
|
32
67
|
|
33
68
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
retry
|
69
|
+
|
70
|
+
describe "with optparse" do
|
71
|
+
|
72
|
+
before(:all) do
|
73
|
+
File.open("#{root}/lib/cron/uses_optparse.rb", 'w') do |file|
|
74
|
+
file << 'File.open("tmp/result", "w") { |file| file << ARGV.join(", ") }'
|
41
75
|
end
|
42
|
-
end
|
76
|
+
end
|
77
|
+
|
78
|
+
after(:each) do
|
79
|
+
FileUtils.rm_rf("tmp/result") rescue nil
|
80
|
+
end
|
43
81
|
|
44
|
-
|
45
|
-
|
82
|
+
after(:all) do
|
83
|
+
FileUtils.rm_rf("#{root}/lib/cron/uses_optparse.rb")
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should pass options after -- to the subcommand" do
|
87
|
+
t = Thread.new { `#{cmd} --wrap uses_optparse --wrap-verbose --wrap-root #{root} --wrap-log log/uses_optparse.log -- --foo bar` }
|
88
|
+
t.join
|
89
|
+
File.read("tmp/result").should == "--foo, bar"
|
90
|
+
end
|
46
91
|
end
|
47
92
|
|
48
93
|
|
49
|
-
|
50
|
-
|
51
|
-
|
94
|
+
|
95
|
+
describe "logging" do
|
96
|
+
it "should create log/awesome_script.log when passed on the commandline" do
|
97
|
+
t = Thread.new { `#{cmd} --wrap awesome_script --wrap-verbose --wrap-root #{root} --wrap-log log/awesome_script.log` }
|
98
|
+
t.join
|
99
|
+
puts "#{Dir.entries(File.join(root,'log')).join(',')}"
|
100
|
+
File.exists?("#{root}/log/awesome_script.log").should == true
|
101
|
+
end
|
52
102
|
end
|
53
103
|
|
54
104
|
|
55
|
-
|
56
|
-
|
57
|
-
|
105
|
+
|
106
|
+
describe "locking" do
|
107
|
+
|
108
|
+
before(:all) do
|
109
|
+
FileUtils.mkdir_p "#{root}/tmp/locks"
|
110
|
+
FileUtils.mkdir_p "#{root}/log"
|
111
|
+
FileUtils.mkdir_p "#{root}/lib/cron"
|
112
|
+
File.open("#{root}/lib/cron/awesome_script.rb", 'w') do |file|
|
113
|
+
file. << 'sleep(2); puts "awesome"'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
before(:each) do
|
118
|
+
@pid = nil
|
119
|
+
remove_lock
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
it "should create a lock file in lock_dir if no lock file exists" do
|
124
|
+
t = Thread.new { `#{cmd} --wrap awesome_script --wrap-verbose --wrap-root #{root} --wrap-log log/awesome_script.log` }
|
125
|
+
Timeout::timeout(3) do
|
126
|
+
begin
|
127
|
+
@pid = File.read "#{root}/tmp/locks/awesome_script.lock"
|
128
|
+
rescue
|
129
|
+
retry
|
130
|
+
end
|
131
|
+
end.should_not raise_error TimeoutError
|
132
|
+
|
133
|
+
@pid.nil?.should_not == true
|
134
|
+
t.join
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
it "should remove the lock file in lock_dir after execution" do
|
139
|
+
`#{cmd} --wrap awesome_script --wrap-root #{root} --wrap-log log/awesome_script.log`
|
140
|
+
File.exists?("tmp/locks/awesome_script.lock").should == false
|
141
|
+
end
|
58
142
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
143
|
+
|
144
|
+
it "should have the pid of the currently executing thread in the lock file" do
|
145
|
+
read_pid = nil
|
146
|
+
@pid = Process.fork { `#{cmd} --wrap awesome_script --wrap-verbose --wrap-root #{root} --wrap-log log/awesome_script.log` }
|
147
|
+
|
148
|
+
begin
|
149
|
+
read_pid = File.read "#{root}/tmp/locks/awesome_script.lock"
|
150
|
+
rescue
|
151
|
+
retry
|
152
|
+
end
|
153
|
+
|
154
|
+
Process.wait
|
155
|
+
@pid.nil?.should == false
|
156
|
+
read_pid.nil?.should == false
|
157
|
+
read_pid.should_not == ''
|
158
|
+
read_pid.should == (@pid + 1).to_s
|
63
159
|
end
|
64
160
|
|
65
|
-
|
66
|
-
|
161
|
+
|
162
|
+
it "should not execute if the lock file is there and the pid is valid" do
|
163
|
+
File.open("#{root}/tmp/locks/awesome_script.lock", 'w') do |file|
|
164
|
+
file << Process::pid
|
165
|
+
end
|
166
|
+
|
167
|
+
start_time = Time.now
|
168
|
+
Process.fork { `#{cmd} --wrap awesome_script --wrap-verbose --wrap-root #{root} --wrap-log log/awesome_script.log` }
|
169
|
+
Process.wait
|
170
|
+
end_time = Time.now
|
171
|
+
|
172
|
+
((end_time - start_time) < 1).should == true
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
it "should execute if the lock file is there but the pid is invalid" do
|
177
|
+
File.open("#{root}/tmp/locks/awesome_script.lock", 'w') do |file|
|
178
|
+
file << 'foo'
|
179
|
+
end
|
180
|
+
|
181
|
+
start_time = Time.now
|
182
|
+
Process.fork { `#{cmd} --wrap awesome_script --wrap-verbose --wrap-root #{root} --wrap-log log/awesome_script.log` }
|
183
|
+
Process.wait
|
184
|
+
end_time = Time.now
|
185
|
+
|
186
|
+
((end_time - start_time) > 2).should == true
|
187
|
+
end
|
67
188
|
end
|
68
189
|
|
69
190
|
|
191
|
+
|
70
192
|
end
|
metadata
CHANGED
@@ -1,42 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cron_wrapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 9
|
10
|
+
version: 0.0.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Bryan Taylor
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
|
-
cert_chain:
|
17
|
-
- |
|
18
|
-
-----BEGIN CERTIFICATE-----
|
19
|
-
MIIDMDCCAhigAwIBAgIBADANBgkqhkiG9w0BAQUFADA+MRIwEAYDVQQDDAlidGF5
|
20
|
-
bG9yMzkxEzARBgoJkiaJk/IsZAEZFgNjc2MxEzARBgoJkiaJk/IsZAEZFgNjb20w
|
21
|
-
HhcNMTEwMjE2MTI1MzQzWhcNMTIwMjE2MTI1MzQzWjA+MRIwEAYDVQQDDAlidGF5
|
22
|
-
bG9yMzkxEzARBgoJkiaJk/IsZAEZFgNjc2MxEzARBgoJkiaJk/IsZAEZFgNjb20w
|
23
|
-
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDid0W3CiAzCKP+H70D/FFq
|
24
|
-
RnwfMdTqsIGK6pKZVHIqqcZxntJw1r3zHwvDwwjh67/iysB0mum6Palizm0xtBqZ
|
25
|
-
wTHO+GXNsTz/+zfihkJMSVhSY8Y58SNuV5m1CmzdVSyVrTyOlkc6+IpHTlpaCpf4
|
26
|
-
r3mGtZbsuEpLvU/A3iC778k8Bm9hoKhI/3CoMWQjSTHYfrMDWetuGhu8NbdGK3BN
|
27
|
-
E1dgEBdQLAjf8yeY3pmmUE88cr9EvrFVdx7mnI5lzOwZMuFSgEBw5AsB6+vvlTW3
|
28
|
-
i75Q4pJwjeM41i2B1u7T4kskmOogfZl3YAulPXrEaTCKHDEQb/Jp4WtTy2v8m+79
|
29
|
-
AgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBS36r/0
|
30
|
-
ouuKO1EVrbluXYEBlANxODANBgkqhkiG9w0BAQUFAAOCAQEAgNN7J2bWCZDSQQm8
|
31
|
-
7PfoCViUKWIcWEZB+C05R0JDpFue0lL5s6aAt61rPXL6k5UiLtj8QkGSe0vasC9G
|
32
|
-
f8eBWU5l3g/HDvsFZ5cIBWk0saF7xlIZC3E98LF8Vcfl9WFibHCuwApxzzcAQvdU
|
33
|
-
ocHFXaTM2tz8iRO5pW+Do3GC7Mjbo2mvAGN0H5f4tZkZ+Ttm25bAPpnHfXaWPxKq
|
34
|
-
RL48Oo1H6iw8nmjm8YrQC6UdtW8ogetCkJwwFmK/U5YQQsE0NnUSG5Ii5R32ZdaY
|
35
|
-
eMvMROg/ZYJZzMayO+XXWYgXhy2UDEP/hNhNzM3E+XJUilcA4dZ/fdX57vL0Qpvn
|
36
|
-
NK5lPw==
|
37
|
-
-----END CERTIFICATE-----
|
16
|
+
cert_chain: []
|
38
17
|
|
39
|
-
date: 2011-02
|
18
|
+
date: 2011-03-02 00:00:00 +00:00
|
40
19
|
default_executable:
|
41
20
|
dependencies: []
|
42
21
|
|
@@ -48,14 +27,14 @@ extensions: []
|
|
48
27
|
|
49
28
|
extra_rdoc_files:
|
50
29
|
- bin/cron_wrapper
|
51
|
-
- lib/cron/
|
30
|
+
- lib/cron/awesome_script.rb
|
52
31
|
- lib/cron_wrapper.rb
|
53
32
|
files:
|
54
33
|
- Manifest
|
55
34
|
- Rakefile
|
56
35
|
- bin/cron_wrapper
|
57
36
|
- cron_wrapper.gemspec
|
58
|
-
- lib/cron/
|
37
|
+
- lib/cron/awesome_script.rb
|
59
38
|
- lib/cron_wrapper.rb
|
60
39
|
- spec/cron_wrapper_spec.rb
|
61
40
|
- spec/spec_helper.rb
|
data.tar.gz.sig
DELETED
Binary file
|
data/lib/cron/foo.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
puts "foo: #{ARGV}"
|
metadata.gz.sig
DELETED
Binary file
|