daemontools 0.2.8 → 0.2.10
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/lib/daemontools/service.rb +194 -0
- data/lib/daemontools/version.rb +1 -1
- data/lib/daemontools.rb +44 -124
- data/spec/service_spec.rb +157 -0
- data/templates/rvm.erb +15 -3
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0406a7ec3beb2cb50e6103fc504b6c245f0051a59404d24832fa10fd3f60af5b
|
|
4
|
+
data.tar.gz: e850a26c07581ca728958072af3a4649b856286ac7756cc5c080adef0da55343
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3947df53ae94a0f59d23e661ea636c31c45a293ad9c2fae5da51a5c0bb4d3d9c4553f724c3400f1c483a88065d2e735a5e365550b11445b1ffcfa45c8b7f8962
|
|
7
|
+
data.tar.gz: 1a71473ab9fbde2e778d98133fc99d207782d9ce3409d7494d5713cffddac408b2f66fcb5161e1212fdb9730d5be0e0348e718a6848457091524591ef63868a1
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
module Daemontools
|
|
2
|
+
class Service
|
|
3
|
+
|
|
4
|
+
CACHED_SERVICES = {}
|
|
5
|
+
|
|
6
|
+
def self.[](name)
|
|
7
|
+
CACHED_SERVICES[name] ||= new(name)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(name)
|
|
11
|
+
@name = name
|
|
12
|
+
@path = "#{Daemontools.svc_root}/#{name}"
|
|
13
|
+
@log_path = "#{@path}/log"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Actions
|
|
17
|
+
|
|
18
|
+
def add(command, options)
|
|
19
|
+
apply_options(command: command, **options)
|
|
20
|
+
|
|
21
|
+
Dir.exist?(@path) ? stop : Dir.mkdir(@path)
|
|
22
|
+
Dir.mkdir(@log_path) unless Dir.exist?(@log_path)
|
|
23
|
+
|
|
24
|
+
File.open("#{@path}/down", 'w') { |f| f.write('') }
|
|
25
|
+
File.open("#{@log_path}/down", 'w') { |f| f.write('') }
|
|
26
|
+
File.open("#{@log_path}/run", 'w', 0o755) { |f| f.write(run_template('log.erb')) }
|
|
27
|
+
File.open("#{@path}/run", 'w', 0o755) { |f| f.write(run_template('run.erb')) }
|
|
28
|
+
|
|
29
|
+
wait_start(options[:wait_timeout]) unless options[:not_wait]
|
|
30
|
+
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def delete(rm_cmd)
|
|
35
|
+
return false unless check_service_exists(false)
|
|
36
|
+
|
|
37
|
+
stop
|
|
38
|
+
sleep 0.3
|
|
39
|
+
cmd = rm_cmd.nil? ? "sudo rm -rf #{@path} 2>&1" : "#{rm_cmd} #{@path}"
|
|
40
|
+
r = `#{cmd}`
|
|
41
|
+
raise r if $?.exitstatus != 0
|
|
42
|
+
|
|
43
|
+
CACHED_SERVICES.delete(@name)
|
|
44
|
+
true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def stop
|
|
48
|
+
run_svc('d')
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def start
|
|
52
|
+
run_svc('u')
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def restart
|
|
56
|
+
run_svc('t')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Statuses
|
|
60
|
+
|
|
61
|
+
def status
|
|
62
|
+
check_service_exists
|
|
63
|
+
r = `sudo svstat #{@path} 2>&1`
|
|
64
|
+
raise r if $?.exitstatus != 0
|
|
65
|
+
raise 'Unknown status' unless r.match(/.*?:\s*(\S+).*\s(\d+) seconds.*/)
|
|
66
|
+
|
|
67
|
+
[::Regexp.last_match(1), ::Regexp.last_match(2).to_i]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def up?
|
|
71
|
+
status[0] == 'up'
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def down?
|
|
75
|
+
status[0] == 'down'
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def check_service_exists(raise_error = true)
|
|
79
|
+
exists = Dir.exist?(@path)
|
|
80
|
+
raise_error && !exists ? raise("Service #{@name} not exists") : exists
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Run States
|
|
84
|
+
|
|
85
|
+
def run_status
|
|
86
|
+
check_service_exists
|
|
87
|
+
File.exist?("#{@path}/down") ? 'down' : 'up'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def run_status_up?
|
|
91
|
+
run_status == 'up'
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def run_status_down?
|
|
95
|
+
run_status == 'down'
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def run_status_up!
|
|
99
|
+
File.delete("#{@path}/down")
|
|
100
|
+
File.delete("#{@log_path}/down") if Dir.exist?(@log_path)
|
|
101
|
+
true
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def run_status_down!
|
|
105
|
+
check_service_exists
|
|
106
|
+
File.open("#{@path}/down", 'w') { |f| f.write('') }
|
|
107
|
+
File.open("#{@log_path}/down", 'w') { |f| f.write('') } if Dir.exist?(@log_path)
|
|
108
|
+
|
|
109
|
+
true
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Tmp Actions
|
|
113
|
+
|
|
114
|
+
def add_empty
|
|
115
|
+
Dir.mkdir(@path) unless Dir.exist?(@path)
|
|
116
|
+
File.open("#{@path}/down", 'w') { |f| f.write('') }
|
|
117
|
+
|
|
118
|
+
wait_start(10)
|
|
119
|
+
|
|
120
|
+
File.delete("#{@path}/down")
|
|
121
|
+
stop
|
|
122
|
+
|
|
123
|
+
true
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def add_empty_tmp
|
|
127
|
+
path = "#{Daemontools.tmp_root}/daemontools_service_#{@name}"
|
|
128
|
+
Dir.mkdir(path) unless Dir.exist?(path)
|
|
129
|
+
|
|
130
|
+
true
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def move_tmp
|
|
134
|
+
tmp_path = "#{Daemontools.tmp_root}/daemontools_service_#{@name}"
|
|
135
|
+
svc_path = @path
|
|
136
|
+
|
|
137
|
+
r = `mv #{tmp_path} #{svc_path}`
|
|
138
|
+
raise r if $?.exitstatus != 0
|
|
139
|
+
raise r unless r.empty?
|
|
140
|
+
|
|
141
|
+
wait_start(10)
|
|
142
|
+
|
|
143
|
+
true
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def tmp_exists?
|
|
147
|
+
Dir.exist?("#{Daemontools.tmp_root}/daemontools_service_#{@name}")
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
private
|
|
151
|
+
|
|
152
|
+
def run_svc(command)
|
|
153
|
+
check_service_exists
|
|
154
|
+
r = `sudo svc -#{command} #{@path} 2>&1`
|
|
155
|
+
raise r if $?.exitstatus != 0
|
|
156
|
+
raise r unless r.empty?
|
|
157
|
+
|
|
158
|
+
return true unless Dir.exist?(@log_path)
|
|
159
|
+
|
|
160
|
+
r = `sudo svc -#{command} #{@log_path} 2>&1`
|
|
161
|
+
raise r if $?.exitstatus != 0
|
|
162
|
+
raise r unless r.empty?
|
|
163
|
+
|
|
164
|
+
true
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def run_template(template_name)
|
|
168
|
+
@user = Etc.getpwuid(Process.uid).name
|
|
169
|
+
template_path = "#{__dir__}/../templates/#{template_name}"
|
|
170
|
+
ERB.new(File.read(template_path)).result(binding)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def apply_options(**options)
|
|
174
|
+
@command = options[:command]
|
|
175
|
+
@log_dir = options[:log_dir] || "#{Daemontools.log_root}/#{@name}"
|
|
176
|
+
@pre_command = options[:pre_command]
|
|
177
|
+
@sleep = options[:sleep] || 3
|
|
178
|
+
@change_user_command = options[:change_user_command]
|
|
179
|
+
@ulimit = options[:ulimit]
|
|
180
|
+
@write_time = options[:write_time]
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def wait_start(wait_timeout = nil)
|
|
184
|
+
wait_timeout ||= 10
|
|
185
|
+
now = Time.now.to_f
|
|
186
|
+
|
|
187
|
+
while `sudo svstat #{@path} 2>&1`.match(/unable to open/i)
|
|
188
|
+
raise 'Timeout wait for svc add service' if Time.now.to_f - now > wait_timeout
|
|
189
|
+
|
|
190
|
+
sleep 0.1
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
data/lib/daemontools/version.rb
CHANGED
data/lib/daemontools.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'daemontools/version'
|
|
2
|
+
require 'daemontools/service'
|
|
2
3
|
require 'daemontools/service_builder'
|
|
3
4
|
require 'daemontools/service_remover'
|
|
4
5
|
require 'etc'
|
|
@@ -12,168 +13,87 @@ module Daemontools
|
|
|
12
13
|
@log_root = '/var/log/svc'
|
|
13
14
|
@tmp_root = '/tmp'
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
check_service_exists(name, false)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def self.tmp_exists?(name)
|
|
20
|
-
Dir.exists?("#{@tmp_root}/daemontools_service_#{name}")
|
|
21
|
-
end
|
|
16
|
+
# Actions
|
|
22
17
|
|
|
23
|
-
def self.
|
|
24
|
-
|
|
25
|
-
r = `sudo svstat #{@path} 2>&1`
|
|
26
|
-
raise r if $?.exitstatus != 0
|
|
27
|
-
raise "Unknown status" unless r.match(/.*?:\s*(\S+).*\s(\d+) seconds.*/)
|
|
28
|
-
[$1, $2.to_i]
|
|
18
|
+
def self.add(name, command, options = {})
|
|
19
|
+
Service[name].add(command, options)
|
|
29
20
|
end
|
|
30
21
|
|
|
31
|
-
def self.
|
|
32
|
-
|
|
22
|
+
def self.delete(name, rm_cmd = nil)
|
|
23
|
+
Service[name].delete(rm_cmd)
|
|
33
24
|
end
|
|
34
25
|
|
|
35
|
-
def self.
|
|
36
|
-
|
|
26
|
+
def self.start(name)
|
|
27
|
+
Service[name].start
|
|
37
28
|
end
|
|
38
29
|
|
|
39
30
|
def self.stop(name)
|
|
40
|
-
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def self.start(name)
|
|
44
|
-
run_svc(name, 'u')
|
|
31
|
+
Service[name].stop
|
|
45
32
|
end
|
|
46
33
|
|
|
47
34
|
def self.restart(name)
|
|
48
|
-
|
|
35
|
+
Service[name].restart
|
|
49
36
|
end
|
|
50
37
|
|
|
51
|
-
|
|
52
|
-
path = "#{@svc_root}/#{name}"
|
|
53
|
-
Dir.mkdir(path) unless Dir.exists?(path)
|
|
54
|
-
File.open("#{path}/down", 'w') {|f| f.write('')}
|
|
55
|
-
now = Time.now.to_f
|
|
56
|
-
while `sudo svstat #{path} 2>&1`.match(/unable to open/i)
|
|
57
|
-
raise "Timeout wait for svc add service" if Time.now.to_f - now > 10
|
|
58
|
-
sleep 0.1
|
|
59
|
-
end
|
|
60
|
-
File.delete("#{path}/down")
|
|
61
|
-
stop(name)
|
|
62
|
-
true
|
|
63
|
-
end
|
|
38
|
+
# Statuses
|
|
64
39
|
|
|
65
|
-
def self.
|
|
66
|
-
|
|
67
|
-
Dir.mkdir(path) unless Dir.exists?(path)
|
|
68
|
-
true
|
|
40
|
+
def self.status(name)
|
|
41
|
+
Service[name].status
|
|
69
42
|
end
|
|
70
43
|
|
|
71
|
-
def self.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
r = `mv #{tmp_path} #{svc_path}`
|
|
76
|
-
raise r if $?.exitstatus != 0
|
|
77
|
-
raise r if ! r.empty?
|
|
78
|
-
|
|
79
|
-
now = Time.now.to_f
|
|
80
|
-
while `sudo svstat #{svc_path} 2>&1`.match(/unable to open/i)
|
|
81
|
-
raise "Timeout wait for svc add service" if Time.now.to_f - now > 10
|
|
82
|
-
sleep 0.1
|
|
83
|
-
end
|
|
44
|
+
def self.up?(name)
|
|
45
|
+
Service[name].up?
|
|
46
|
+
end
|
|
84
47
|
|
|
85
|
-
|
|
48
|
+
def self.down?(name)
|
|
49
|
+
Service[name].down?
|
|
86
50
|
end
|
|
87
51
|
|
|
88
|
-
def self.
|
|
89
|
-
|
|
90
|
-
@command = command
|
|
91
|
-
@log_dir = options[:log_dir] || "#{@log_root}/#{@name}"
|
|
92
|
-
@pre_command = options[:pre_command]
|
|
93
|
-
@sleep = options[:sleep] || 3
|
|
94
|
-
@path = "#{@svc_root}/#{name}"
|
|
95
|
-
@change_user_command = options[:change_user_command]
|
|
96
|
-
@ulimit = options[:ulimit]
|
|
97
|
-
@write_time = options[:write_time]
|
|
98
|
-
|
|
99
|
-
if Dir.exists?(@path)
|
|
100
|
-
stop(name)
|
|
101
|
-
else
|
|
102
|
-
Dir.mkdir(@path)
|
|
103
|
-
end
|
|
104
|
-
File.open("#{@path}/down", 'w') {|f| f.write('')}
|
|
105
|
-
Dir.mkdir("#{@path}/log") unless Dir.exists?("#{@path}/log")
|
|
106
|
-
File.open("#{@path}/log/run", 'w', 0755) {|f| f.write(run_template('log.erb'))}
|
|
107
|
-
File.open("#{@path}/run", 'w', 0755) {|f| f.write(run_template('run.erb'))}
|
|
108
|
-
|
|
109
|
-
unless options[:not_wait]
|
|
110
|
-
wait_timeout = options[:wait_timeout] || 10
|
|
111
|
-
now = Time.now.to_f
|
|
112
|
-
while `sudo svstat #{@path} 2>&1`.match(/unable to open/i)
|
|
113
|
-
raise "Timeout wait for svc add service" if Time.now.to_f - now > wait_timeout
|
|
114
|
-
sleep 0.1
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
true
|
|
52
|
+
def self.exists?(name)
|
|
53
|
+
Service[name].check_service_exists(false)
|
|
119
54
|
end
|
|
120
55
|
|
|
121
|
-
def self.
|
|
122
|
-
|
|
123
|
-
stop(name)
|
|
124
|
-
sleep 0.3
|
|
125
|
-
cmd = rm_cmd.nil? ? "sudo rm -rf #{@path} 2>&1" : "#{rm_cmd} #{@path}"
|
|
126
|
-
r = `#{cmd}`
|
|
127
|
-
raise r if $?.exitstatus != 0
|
|
128
|
-
true
|
|
56
|
+
def self.check_service_exists(name, raise_error = true)
|
|
57
|
+
Service[name].check_service_exists(raise_error)
|
|
129
58
|
end
|
|
130
59
|
|
|
60
|
+
# Run States
|
|
61
|
+
|
|
131
62
|
def self.run_status(name)
|
|
132
|
-
|
|
133
|
-
File.exists?("#{@path}/down") ? "down" : "up"
|
|
63
|
+
Service[name].run_status
|
|
134
64
|
end
|
|
135
65
|
|
|
136
66
|
def self.run_status_up?(name)
|
|
137
|
-
|
|
67
|
+
Service[name].run_status_up?
|
|
138
68
|
end
|
|
139
69
|
|
|
140
70
|
def self.run_status_down?(name)
|
|
141
|
-
|
|
71
|
+
Service[name].run_status_down?
|
|
142
72
|
end
|
|
143
73
|
|
|
144
74
|
def self.make_run_status_up(name)
|
|
145
|
-
|
|
146
|
-
true
|
|
75
|
+
Service[name].run_status_up!
|
|
147
76
|
end
|
|
148
77
|
|
|
149
78
|
def self.make_run_status_down(name)
|
|
150
|
-
|
|
151
|
-
File.open("#{@path}/down", 'w') {|f| f.write('')}
|
|
152
|
-
true
|
|
79
|
+
Service[name].run_status_down!
|
|
153
80
|
end
|
|
154
81
|
|
|
155
|
-
|
|
82
|
+
# Tmp Actions
|
|
156
83
|
|
|
157
|
-
def self.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
true
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def self.run_template(template_name)
|
|
175
|
-
@user = Etc.getpwuid(Process.uid).name
|
|
176
|
-
template_path = File.expand_path(File.dirname(__FILE__))+'/../templates/'+template_name
|
|
177
|
-
ERB.new(File.read(template_path)).result(binding())
|
|
84
|
+
def self.add_empty(name)
|
|
85
|
+
Service[name].add_empty
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def self.add_empty_tmp(name)
|
|
89
|
+
Service[name].add_empty_tmp
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.move_tmp(name)
|
|
93
|
+
Service[name].move_tmp
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.tmp_exists?(name)
|
|
97
|
+
Service[name].tmp_exists?
|
|
178
98
|
end
|
|
179
99
|
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
require 'daemontools'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Daemontools::Service do
|
|
4
|
+
let(:svc_root) { '/tmp/svc_root' }
|
|
5
|
+
let(:tmp_root) { '/tmp/tmp_root' }
|
|
6
|
+
let(:log_root) { '/tmp/log_root' }
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
stub_const('Daemontools::Service::CACHED_SERVICES', {})
|
|
10
|
+
|
|
11
|
+
allow(Daemontools).to receive(:svc_root).and_return(svc_root)
|
|
12
|
+
allow(Daemontools).to receive(:tmp_root).and_return(tmp_root)
|
|
13
|
+
allow(Daemontools).to receive(:log_root).and_return(log_root)
|
|
14
|
+
|
|
15
|
+
FileUtils.mkdir_p(svc_root)
|
|
16
|
+
FileUtils.mkdir_p(tmp_root)
|
|
17
|
+
FileUtils.mkdir_p(log_root)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
after do
|
|
21
|
+
FileUtils.rm_rf(svc_root)
|
|
22
|
+
FileUtils.rm_rf(tmp_root)
|
|
23
|
+
FileUtils.rm_rf(log_root)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '.[]' do
|
|
27
|
+
it 'caches and returns the same instance for the same name' do
|
|
28
|
+
s1 = described_class['test']
|
|
29
|
+
s2 = described_class['test']
|
|
30
|
+
expect(s1).to be_a(described_class)
|
|
31
|
+
expect(s1).to equal(s2)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe '#check_service_exists' do
|
|
36
|
+
let(:service) { described_class.new('svc1') }
|
|
37
|
+
|
|
38
|
+
it 'returns false when the directory does not exist' do
|
|
39
|
+
expect(service.check_service_exists(false)).to be false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'raises an error when directory is missing and raise_error=true' do
|
|
43
|
+
expect { service.check_service_exists(true) }.to raise_error(/not exists/)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'returns true when the directory exists' do
|
|
47
|
+
FileUtils.mkdir_p("#{svc_root}/svc1")
|
|
48
|
+
expect(service.check_service_exists(false)).to be true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe '#delete' do
|
|
53
|
+
let(:service) { described_class.new('svc1') }
|
|
54
|
+
|
|
55
|
+
before do
|
|
56
|
+
FileUtils.mkdir_p("#{svc_root}/svc1")
|
|
57
|
+
allow(service).to receive(:stop).and_return(true)
|
|
58
|
+
allow(service).to receive(:`).and_return('')
|
|
59
|
+
allow($?).to receive(:exitstatus).and_return(0)
|
|
60
|
+
Daemontools::Service::CACHED_SERVICES['svc1'] = service
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'removes the service from cache and returns true' do
|
|
64
|
+
expect(service.delete(nil)).to be true
|
|
65
|
+
expect(Daemontools::Service::CACHED_SERVICES).not_to have_key('svc1')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'returns false when service does not exist' do
|
|
69
|
+
FileUtils.rm_rf("#{svc_root}/svc1")
|
|
70
|
+
expect(service.delete(nil)).to be false
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'raises an error when command exit status is non‑zero' do
|
|
74
|
+
allow($?).to receive(:exitstatus).and_return(1)
|
|
75
|
+
expect { service.delete(nil) }.to raise_error(RuntimeError)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe '#status' do
|
|
80
|
+
let(:service) { described_class.new('svc2') }
|
|
81
|
+
let(:output) { 'svc2: up (pid 1234) 5 seconds' }
|
|
82
|
+
|
|
83
|
+
before do
|
|
84
|
+
FileUtils.mkdir_p("#{svc_root}/svc2")
|
|
85
|
+
allow(service).to receive(:`).and_return(output)
|
|
86
|
+
allow($?).to receive(:exitstatus).and_return(0)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'returns [status, seconds] for valid svstat output' do
|
|
90
|
+
expect(service.status).to eq(%w[up 5].tap { |a| a[1] = 5 })
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'raises "Unknown status" for unexpected output' do
|
|
94
|
+
allow(service).to receive(:`).and_return('something weird')
|
|
95
|
+
expect { service.status }.to raise_error('Unknown status')
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'raises an error when command fails' do
|
|
99
|
+
allow($?).to receive(:exitstatus).and_return(1)
|
|
100
|
+
expect { service.status }.to raise_error(/svc2/)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe '#run_status_*' do
|
|
105
|
+
let(:service) { described_class.new('svc3') }
|
|
106
|
+
|
|
107
|
+
before do
|
|
108
|
+
FileUtils.mkdir_p("#{svc_root}/svc3")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'returns "up" when no down file exists' do
|
|
112
|
+
expect(service.run_status).to eq('up')
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'returns "down" when down file exists' do
|
|
116
|
+
FileUtils.touch("#{svc_root}/svc3/down")
|
|
117
|
+
expect(service.run_status).to eq('down')
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it '#run_status_up! removes down files' do
|
|
121
|
+
FileUtils.mkdir_p("#{svc_root}/svc3/log")
|
|
122
|
+
FileUtils.touch("#{svc_root}/svc3/down")
|
|
123
|
+
FileUtils.touch("#{svc_root}/svc3/log/down")
|
|
124
|
+
service.run_status_up!
|
|
125
|
+
expect(File).not_to exist("#{svc_root}/svc3/down")
|
|
126
|
+
expect(File).not_to exist("#{svc_root}/svc3/log/down")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it '#run_status_down! creates down files' do
|
|
130
|
+
FileUtils.mkdir_p("#{svc_root}/svc3/log")
|
|
131
|
+
service.run_status_down!
|
|
132
|
+
expect(File).to exist("#{svc_root}/svc3/down")
|
|
133
|
+
expect(File).to exist("#{svc_root}/svc3/log/down")
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
describe '#tmp_exists?' do
|
|
138
|
+
let(:service) { described_class.new('svc_tmp') }
|
|
139
|
+
|
|
140
|
+
it 'returns true when temporary directory exists' do
|
|
141
|
+
FileUtils.mkdir_p("#{tmp_root}/daemontools_service_svc_tmp")
|
|
142
|
+
expect(service.tmp_exists?).to be true
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'returns false when temporary directory is missing' do
|
|
146
|
+
FileUtils.rm_rf("#{tmp_root}/daemontools_service_svc_tmp")
|
|
147
|
+
expect(service.tmp_exists?).to be false
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
describe '.CACHED_SERVICES' do
|
|
152
|
+
it 'holds created instances' do
|
|
153
|
+
s1 = described_class['foo']
|
|
154
|
+
expect(Daemontools::Service::CACHED_SERVICES['foo']).to eq(s1)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
data/templates/rvm.erb
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
-
/bin/bash -l -c '
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/bin/bash -l -c '
|
|
2
|
+
<%= @command.gsub('&&', "\n") %> 2>&1 &
|
|
3
|
+
pid=$!
|
|
4
|
+
pgid=$(ps -o pgid= -p $pid | tr -d " ")
|
|
5
|
+
|
|
6
|
+
trap "
|
|
7
|
+
echo \"Sending SIGTERM to main process PID \$pid\"
|
|
8
|
+
kill -TERM \$pid
|
|
9
|
+
sleep 0.5
|
|
10
|
+
echo \"Sending SIGKILL to process group PGID \$pgid\"
|
|
11
|
+
kill -KILL -\$pgid
|
|
12
|
+
" EXIT INT TERM
|
|
13
|
+
|
|
14
|
+
wait $pid
|
|
15
|
+
'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: daemontools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- sh
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -75,11 +75,13 @@ files:
|
|
|
75
75
|
- fixtures/stubs/service_remover_stub.rb
|
|
76
76
|
- lib/daemontools.rb
|
|
77
77
|
- lib/daemontools/capistrano.rb
|
|
78
|
+
- lib/daemontools/service.rb
|
|
78
79
|
- lib/daemontools/service_builder.rb
|
|
79
80
|
- lib/daemontools/service_remover.rb
|
|
80
81
|
- lib/daemontools/version.rb
|
|
81
82
|
- spec/builder_spec.rb
|
|
82
83
|
- spec/service_delete_spec.rb
|
|
84
|
+
- spec/service_spec.rb
|
|
83
85
|
- spec/spec_helper.rb
|
|
84
86
|
- templates/log.erb
|
|
85
87
|
- templates/run.erb
|
|
@@ -109,4 +111,5 @@ summary: Distributed storage
|
|
|
109
111
|
test_files:
|
|
110
112
|
- spec/builder_spec.rb
|
|
111
113
|
- spec/service_delete_spec.rb
|
|
114
|
+
- spec/service_spec.rb
|
|
112
115
|
- spec/spec_helper.rb
|