bluepill 0.0.70 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +158 -171
- data/bin/bluepill +5 -5
- data/bluepill.gemspec +19 -17
- data/lib/bluepill/application.rb +2 -2
- data/lib/bluepill/condition_watch.rb +1 -1
- data/lib/bluepill/logger.rb +2 -2
- data/lib/bluepill/process.rb +35 -37
- data/lib/bluepill/process_conditions/zombie_process.rb +1 -1
- data/lib/bluepill/system.rb +11 -12
- data/lib/bluepill/triggers/flapping.rb +1 -1
- data/lib/bluepill/version.rb +6 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c7760cf13b7c5d2f991f644fe1f762eca7853d3
|
4
|
+
data.tar.gz: 28dc84d8bf94f0e2c5318f9397190fd35f6b626e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76da9cf314f0a7bb9f4181d895e321f9851bc801955e8bde47b10ec9b1ad6f41f8f0d58e9ef3c5f2d1144258272d772579e1fb3204d883cd71ed6ad9dcc076ee
|
7
|
+
data.tar.gz: e25c6b9194bcc135e1a08339b58584c2962e9bc81129c019a91e5d162f52d8eeea73f63bb8195a77cef9191bdc423270725da0a6b1fee39ba7dd9045ef0b5daa
|
data/README.md
CHANGED
@@ -33,24 +33,24 @@ Bluepill organizes processes into 3 levels: application -> group -> process. Eac
|
|
33
33
|
The minimum config file looks something like this:
|
34
34
|
|
35
35
|
```ruby
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
Bluepill.application("app_name") do |app|
|
37
|
+
app.process("process_name") do |process|
|
38
|
+
process.start_command = "/usr/bin/some_start_command"
|
39
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
40
|
+
end
|
41
|
+
end
|
42
42
|
```
|
43
43
|
|
44
44
|
Note that since we specified a PID file and start command, bluepill assumes the process will daemonize itself. If we wanted bluepill to daemonize it for us, we can do (note we still need to specify a PID file):
|
45
45
|
|
46
46
|
```ruby
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
Bluepill.application("app_name") do |app|
|
48
|
+
app.process("process_name") do |process|
|
49
|
+
process.start_command = "/usr/bin/some_start_command"
|
50
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
51
|
+
process.daemonize = true
|
52
|
+
end
|
53
|
+
end
|
54
54
|
```
|
55
55
|
|
56
56
|
If you don't specify a stop command, a TERM signal will be sent by default. Similarly, the default restart action is to issue stop and then start.
|
@@ -58,14 +58,13 @@ If you don't specify a stop command, a TERM signal will be sent by default.
|
|
58
58
|
Now if we want to do something more meaningful, like actually monitor the process, we do:
|
59
59
|
|
60
60
|
```ruby
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
61
|
+
Bluepill.application("app_name") do |app|
|
62
|
+
app.process("process_name") do |process|
|
63
|
+
process.start_command = "/usr/bin/some_start_command"
|
64
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
65
|
+
process.checks :cpu_usage, every: 10.seconds, below: 5, times: 3
|
66
|
+
end
|
67
|
+
end
|
69
68
|
```
|
70
69
|
|
71
70
|
We added a line that checks every 10 seconds to make sure the cpu usage of this process is below 5 percent; 3 failed checks results in a restart. We can specify a two-element array for the _times_ option to say that it 3 out of 5 failed attempts results in a restart.
|
@@ -73,163 +72,155 @@ We added a line that checks every 10 seconds to make sure the cpu usage of this
|
|
73
72
|
To watch memory usage, we just add one more line:
|
74
73
|
|
75
74
|
```ruby
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
75
|
+
Bluepill.application("app_name") do |app|
|
76
|
+
app.process("process_name") do |process|
|
77
|
+
process.start_command = "/usr/bin/some_start_command"
|
78
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
79
|
+
process.checks :cpu_usage, every: 10.seconds, below: 5, times: 3
|
80
|
+
process.checks :mem_usage, every: 10.seconds, below: 100.megabytes, times: [3,5]
|
81
|
+
end
|
82
|
+
end
|
85
83
|
```
|
86
84
|
|
87
85
|
To watch the modification time of a file, e.g. a log file to ensure the process is actually working add one more line:
|
88
86
|
|
89
87
|
```ruby
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
```
|
88
|
+
Bluepill.application("app_name") do |app|
|
89
|
+
app.process("process_name") do |process|
|
90
|
+
process.start_command = "/usr/bin/some_start_command"
|
91
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
92
|
+
process.checks :cpu_usage, every: 10.seconds, below: 5, times: 3
|
93
|
+
process.checks :mem_usage, every: 10.seconds, below: 100.megabytes, times: [3,5]
|
94
|
+
process.checks :file_time, every: 60.seconds, below: 3.minutes, filename: "/tmp/some_file.log", times: 2
|
95
|
+
end
|
96
|
+
end
|
97
|
+
```
|
101
98
|
|
102
99
|
To restart process if it's running too long:
|
103
100
|
|
104
101
|
```ruby
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
```
|
114
|
-
|
115
|
-
|
102
|
+
Bluepill.application("app_name") do |app|
|
103
|
+
app.process("process_name") do |process|
|
104
|
+
process.start_command = "/usr/bin/some_start_command"
|
105
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
106
|
+
process.checks :running_time, every: 10.minutes, below: 24.hours
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
116
110
|
|
117
111
|
We can tell bluepill to give a process some grace time to start/stop/restart before resuming monitoring:
|
118
112
|
|
119
113
|
```ruby
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
end
|
114
|
+
Bluepill.application("app_name") do |app|
|
115
|
+
app.process("process_name") do |process|
|
116
|
+
process.start_command = "/usr/bin/some_start_command"
|
117
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
118
|
+
process.start_grace_time = 3.seconds
|
119
|
+
process.stop_grace_time = 5.seconds
|
120
|
+
process.restart_grace_time = 8.seconds
|
121
|
+
process.checks :cpu_usage, every: 10.seconds, below: 5, times: 3
|
122
|
+
process.checks :mem_usage, every: 10.seconds, below: 100.megabytes, times: [3,5]
|
123
|
+
end
|
124
|
+
end
|
132
125
|
```
|
133
126
|
|
134
127
|
We can group processes by name:
|
135
128
|
|
136
129
|
```ruby
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
end
|
144
|
-
end
|
130
|
+
Bluepill.application("app_name") do |app|
|
131
|
+
5.times do |i|
|
132
|
+
app.process("process_name_#{i}") do |process|
|
133
|
+
process.group = "mongrels"
|
134
|
+
process.start_command = "/usr/bin/some_start_command"
|
135
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
145
136
|
end
|
137
|
+
end
|
138
|
+
end
|
146
139
|
```
|
147
140
|
|
148
141
|
If you want to run the process as someone other than root:
|
149
142
|
|
150
143
|
```ruby
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
end
|
144
|
+
Bluepill.application("app_name") do |app|
|
145
|
+
app.process("process_name") do |process|
|
146
|
+
process.start_command = "/usr/bin/some_start_command"
|
147
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
148
|
+
process.uid = "deploy"
|
149
|
+
process.gid = "deploy"
|
150
|
+
process.checks :cpu_usage, every: 10.seconds, below: 5, times: 3
|
151
|
+
process.checks :mem_usage, every: 10.seconds, below: 100.megabytes, times: [3,5]
|
152
|
+
end
|
153
|
+
end
|
162
154
|
```
|
163
155
|
|
164
156
|
If you want to include one or more supplementary groups:
|
165
157
|
|
166
158
|
```ruby
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
end
|
159
|
+
Bluepill.application("app_name") do |app|
|
160
|
+
app.process("process_name") do |process|
|
161
|
+
process.start_command = "/usr/bin/some_start_command"
|
162
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
163
|
+
process.uid = "deploy"
|
164
|
+
process.gid = "deploy"
|
165
|
+
process.supplementary_groups = ['rvm']
|
166
|
+
process.checks :cpu_usage, every: 10.seconds, below: 5, times: 3
|
167
|
+
process.checks :mem_usage, every: 10.seconds, below: 100.megabytes, times: [3,5]
|
168
|
+
end
|
169
|
+
end
|
179
170
|
```
|
180
171
|
|
181
172
|
You can also set an app-wide uid/gid:
|
182
173
|
|
183
174
|
```ruby
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
175
|
+
Bluepill.application("app_name") do |app|
|
176
|
+
app.uid = "deploy"
|
177
|
+
app.gid = "deploy"
|
178
|
+
app.process("process_name") do |process|
|
179
|
+
process.start_command = "/usr/bin/some_start_command"
|
180
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
181
|
+
end
|
182
|
+
end
|
192
183
|
```
|
193
184
|
|
194
|
-
To track resources of child processes, use
|
185
|
+
To track resources of child processes, use `:include_children`:
|
195
186
|
```ruby
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
187
|
+
Bluepill.application("app_name") do |app|
|
188
|
+
app.process("process_name") do |process|
|
189
|
+
process.start_command = "/usr/bin/some_start_command"
|
190
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
191
|
+
process.checks :mem_usage, every: 1.seconds, below: 5.megabytes, times: [3,5], include_children: true
|
192
|
+
end
|
193
|
+
end
|
203
194
|
```
|
204
195
|
|
205
196
|
To check for flapping:
|
206
197
|
|
207
198
|
```ruby
|
208
|
-
|
199
|
+
process.checks :flapping, times: 2, within: 30.seconds, retry_in: 7.seconds
|
209
200
|
```
|
210
201
|
|
211
|
-
To set the working directory to
|
202
|
+
To set the working directory to `cd` into when starting the command:
|
212
203
|
|
213
204
|
```ruby
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
205
|
+
Bluepill.application("app_name") do |app|
|
206
|
+
app.process("process_name") do |process|
|
207
|
+
process.start_command = "/usr/bin/some_start_command"
|
208
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
209
|
+
process.working_dir = "/path/to/some_directory"
|
210
|
+
end
|
211
|
+
end
|
221
212
|
```
|
222
213
|
|
223
214
|
You can also have an app-wide working directory:
|
224
215
|
|
225
216
|
```ruby
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
217
|
+
Bluepill.application("app_name") do |app|
|
218
|
+
app.working_dir = "/path/to/some_directory"
|
219
|
+
app.process("process_name") do |process|
|
220
|
+
process.start_command = "/usr/bin/some_start_command"
|
221
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
222
|
+
end
|
223
|
+
end
|
233
224
|
```
|
234
225
|
|
235
226
|
Note: We also set the PWD in the environment to the working dir you specify. This is useful for when the working dir is a symlink. Unicorn in particular will cd into the environment variable in PWD when it re-execs to deal with a change in the symlink.
|
@@ -238,25 +229,25 @@ By default, bluepill will send a SIGTERM to your process when stopping.
|
|
238
229
|
To change the stop command:
|
239
230
|
|
240
231
|
```ruby
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
232
|
+
Bluepill.application("app_name") do |app|
|
233
|
+
app.process("process_name") do |process|
|
234
|
+
process.start_command = "/usr/bin/some_start_command"
|
235
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
236
|
+
process.stop_command = "/user/bin/some_stop_command"
|
237
|
+
end
|
238
|
+
end
|
248
239
|
```
|
249
240
|
|
250
241
|
If you'd like to send a signal or signals to your process to stop it:
|
251
242
|
|
252
243
|
```ruby
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
244
|
+
Bluepill.application("app_name") do |app|
|
245
|
+
app.process("process_name") do |process|
|
246
|
+
process.start_command = "/usr/bin/some_start_command"
|
247
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
248
|
+
process.stop_signals = [:quit, 30.seconds, :term, 5.seconds, :kill]
|
249
|
+
end
|
250
|
+
end
|
260
251
|
```
|
261
252
|
|
262
253
|
We added a line that will send a SIGQUIT, wait 30 seconds and check to
|
@@ -266,42 +257,39 @@ to see if the process is still up, and finally send a SIGKILL.
|
|
266
257
|
And lastly, to monitor child processes:
|
267
258
|
|
268
259
|
```ruby
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
end
|
260
|
+
process.monitor_children do |child_process|
|
261
|
+
child_process.checks :cpu_usage, every: 10, below: 5, times: 3
|
262
|
+
child_process.checks :mem_usage, every: 10, below: 100.megabytes, times: [3, 5]
|
263
|
+
child_process.stop_command = "kill -QUIT {{PID}}"
|
264
|
+
end
|
275
265
|
```
|
276
266
|
|
277
267
|
Note {{PID}} will be substituted for the pid of process in both the stop and restart commands.
|
278
268
|
|
279
269
|
### A Note About Output Redirection
|
280
270
|
|
281
|
-
While you can specify shell tricks like the following in the start_command of a process:
|
271
|
+
While you can specify shell tricks like the following in the `start_command` of a process:
|
282
272
|
|
283
273
|
```ruby
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
274
|
+
Bluepill.application("app_name") do |app|
|
275
|
+
app.process("process_name") do |process|
|
276
|
+
process.start_command = "cd /tmp/some_dir && SOME_VAR=1 /usr/bin/some_start_command > /tmp/server.log 2>&1"
|
277
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
278
|
+
end
|
279
|
+
end
|
290
280
|
```
|
291
281
|
|
292
282
|
We recommend that you _not_ do that and instead use the config options to capture output from your daemons. Like so:
|
293
283
|
|
294
284
|
```ruby
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
end
|
304
|
-
end
|
285
|
+
Bluepill.application("app_name") do |app|
|
286
|
+
app.process("process_name") do |process|
|
287
|
+
process.start_command = "/usr/bin/env SOME_VAR=1 /usr/bin/some_start_command"
|
288
|
+
process.working_dir = "/tmp/some_dir"
|
289
|
+
process.stdout = process.stderr = "/tmp/server.log"
|
290
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
291
|
+
end
|
292
|
+
end
|
305
293
|
```
|
306
294
|
|
307
295
|
The main benefit of using the config options is that Bluepill will be able to monitor the correct process instead of just watching the shell that spawned your actual server.
|
@@ -347,9 +335,9 @@ To quit the bluepill daemon for an application:
|
|
347
335
|
By default, bluepill uses syslog local6 facility as described in the installation section. But if for any reason you don't want to use syslog, you can use a log file. You can do this by setting the :log\_file option in the config:
|
348
336
|
|
349
337
|
```ruby
|
350
|
-
|
351
|
-
|
352
|
-
|
338
|
+
Bluepill.application("app_name", log_file: "/path/to/bluepill.log") do |app|
|
339
|
+
# ...
|
340
|
+
end
|
353
341
|
```
|
354
342
|
|
355
343
|
Keep in mind that you still need to set up log rotation (described in the installation section) to keep the log file from growing huge.
|
@@ -358,9 +346,9 @@ Keep in mind that you still need to set up log rotation (described in the instal
|
|
358
346
|
You can run bluepill in the foreground:
|
359
347
|
|
360
348
|
```ruby
|
361
|
-
|
362
|
-
|
363
|
-
|
349
|
+
Bluepill.application("app_name", foreground: true) do |app|
|
350
|
+
# ...
|
351
|
+
end
|
364
352
|
```
|
365
353
|
|
366
354
|
Note that You must define only one application per config when using foreground mode.
|
@@ -377,7 +365,6 @@ Note that You must define only one application per config when using foreground
|
|
377
365
|
This library aims to support and is [tested against][travis] the following Ruby
|
378
366
|
implementations:
|
379
367
|
|
380
|
-
* Ruby 1.8.7
|
381
368
|
* Ruby 1.9.3
|
382
369
|
* Ruby 2.0.0
|
383
370
|
* Ruby 2.1
|
data/bin/bluepill
CHANGED
@@ -11,11 +11,11 @@ RbConfig = Config unless Object.const_defined?(:RbConfig)
|
|
11
11
|
|
12
12
|
# Default options
|
13
13
|
options = {
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
14
|
+
log_file: '/var/log/bluepill.log',
|
15
|
+
base_dir: ENV['BLUEPILL_BASE_DIR'] || (::Process.euid != 0 ? File.join(ENV['HOME'], '.bluepill') : '/var/run/bluepill'),
|
16
|
+
privileged: true,
|
17
|
+
timeout: 10,
|
18
|
+
attempts: 1,
|
19
19
|
}
|
20
20
|
|
21
21
|
OptionParser.new do |opts|
|
data/bluepill.gemspec
CHANGED
@@ -2,23 +2,25 @@ lib = File.expand_path('../lib', __FILE__)
|
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
3
|
require 'bluepill/version'
|
4
4
|
|
5
|
-
Gem::Specification.new do |
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'bluepill'
|
7
|
+
spec.version = Bluepill::Version
|
8
|
+
spec.platform = Gem::Platform::RUBY
|
9
|
+
spec.authors = ['Arya Asemanfar', 'Gary Tsang', 'Rohith Ravi']
|
10
|
+
spec.email = ['entombedvirus@gmail.com']
|
11
|
+
spec.homepage = 'http://github.com/bluepill-rb/bluepill'
|
12
|
+
spec.summary = 'A process monitor written in Ruby with stability and minimalism in mind.'
|
13
|
+
spec.description = "Bluepill keeps your daemons up while taking up as little resources as possible. After all you probably want the resources of your server to be used by whatever daemons you are running rather than the thing that's supposed to make sure they are brought back up, should they die or misbehave."
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
spec.add_dependency 'activesupport', ['>= 3.2', '< 5']
|
17
|
+
spec.add_dependency 'blue-daemons', '~> 1.1'
|
18
|
+
spec.add_dependency 'state_machine', '~> 1.1'
|
19
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
spec.required_ruby_version = '>= 1.9.3'
|
22
|
+
|
23
|
+
spec.files = %w(CONTRIBUTING.md DESIGN.md LICENSE README.md bluepill.gemspec) + Dir['bin/*'] + Dir['lib/**/*.rb']
|
24
|
+
spec.executables = Dir['bin/*'].collect { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ['lib']
|
24
26
|
end
|
data/lib/bluepill/application.rb
CHANGED
@@ -24,7 +24,7 @@ module Bluepill
|
|
24
24
|
|
25
25
|
self.groups = {}
|
26
26
|
|
27
|
-
self.logger = ProcessJournal.logger = Bluepill::Logger.new(:
|
27
|
+
self.logger = ProcessJournal.logger = Bluepill::Logger.new(log_file: log_file, stdout: foreground?).prefix_with(self.name)
|
28
28
|
|
29
29
|
setup_signal_traps
|
30
30
|
setup_pids_dir
|
@@ -60,7 +60,7 @@ module Bluepill
|
|
60
60
|
def add_process(process, group_name = nil)
|
61
61
|
group_name = group_name.to_s if group_name
|
62
62
|
|
63
|
-
groups[group_name] ||= Group.new(group_name, :
|
63
|
+
groups[group_name] ||= Group.new(group_name, logger: logger.prefix_with(group_name))
|
64
64
|
groups[group_name].add_process(process)
|
65
65
|
end
|
66
66
|
|
@@ -12,7 +12,7 @@ module Bluepill
|
|
12
12
|
@fires = options.key?(:fires) ? Array(options.delete(:fires)) : [:restart]
|
13
13
|
@every = options.delete(:every)
|
14
14
|
@times = options.delete(:times) || [1, 1]
|
15
|
-
@times = [@times, @times] unless @times.is_a?(Array) # handles :
|
15
|
+
@times = [@times, @times] unless @times.is_a?(Array) # handles times: 5
|
16
16
|
@include_children = options.delete(:include_children) || false
|
17
17
|
|
18
18
|
self.clear_history!
|
data/lib/bluepill/logger.rb
CHANGED
@@ -28,7 +28,7 @@ module Bluepill
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def prefix_with(prefix)
|
31
|
-
@prefixes[prefix] ||= self.class.new(:
|
31
|
+
@prefixes[prefix] ||= self.class.new(logger: self, prefix: prefix)
|
32
32
|
end
|
33
33
|
|
34
34
|
def reopen
|
@@ -52,7 +52,7 @@ module Bluepill
|
|
52
52
|
|
53
53
|
class LoggerAdapter < ::Logger
|
54
54
|
LOGGER_EQUIVALENTS =
|
55
|
-
{:
|
55
|
+
{debug: :debug, err: :error, warning: :warn, info: :info, emerg: :fatal, alert: :warn, crit: :fatal, notice: :info}
|
56
56
|
|
57
57
|
LOG_METHODS.each do |method|
|
58
58
|
next if method == LOGGER_EQUIVALENTS[method]
|
data/lib/bluepill/process.rb
CHANGED
@@ -55,7 +55,7 @@ module Bluepill
|
|
55
55
|
attr_accessor(*CONFIGURABLE_ATTRIBUTES)
|
56
56
|
attr_reader :children, :statistics
|
57
57
|
|
58
|
-
state_machine :
|
58
|
+
state_machine initial: :unmonitored do
|
59
59
|
# These are the idle states, i.e. only an event (either external or internal) will trigger a transition.
|
60
60
|
# The distinction between down and unmonitored is that down
|
61
61
|
# means we know it is not running and unmonitored is that we don't care if it's running.
|
@@ -65,22 +65,22 @@ module Bluepill
|
|
65
65
|
state :starting, :stopping, :restarting
|
66
66
|
|
67
67
|
event :tick do
|
68
|
-
transition :
|
69
|
-
transition :
|
68
|
+
transition starting: :up, if: :process_running?
|
69
|
+
transition starting: :down, unless: :process_running?
|
70
70
|
|
71
|
-
transition :
|
72
|
-
transition :
|
71
|
+
transition up: :up, if: :process_running?
|
72
|
+
transition up: :down, unless: :process_running?
|
73
73
|
|
74
74
|
# The process failed to die after entering the stopping state. Change the state to reflect
|
75
75
|
# reality.
|
76
|
-
transition :
|
77
|
-
transition :
|
76
|
+
transition stopping: :up, if: :process_running?
|
77
|
+
transition stopping: :down, unless: :process_running?
|
78
78
|
|
79
|
-
transition :
|
80
|
-
transition :
|
79
|
+
transition down: :up, if: :process_running?
|
80
|
+
transition down: :starting, unless: :process_running?
|
81
81
|
|
82
|
-
transition :
|
83
|
-
transition :
|
82
|
+
transition restarting: :up, if: :process_running?
|
83
|
+
transition restarting: :down, unless: :process_running?
|
84
84
|
end
|
85
85
|
|
86
86
|
event :start do
|
@@ -88,7 +88,7 @@ module Bluepill
|
|
88
88
|
end
|
89
89
|
|
90
90
|
event :stop do
|
91
|
-
transition :
|
91
|
+
transition up: :stopping
|
92
92
|
end
|
93
93
|
|
94
94
|
event :unmonitor do
|
@@ -99,14 +99,14 @@ module Bluepill
|
|
99
99
|
transition [:up, :down] => :restarting
|
100
100
|
end
|
101
101
|
|
102
|
-
before_transition any => any, :
|
103
|
-
before_transition :
|
102
|
+
before_transition any => any, do: :notify_triggers
|
103
|
+
before_transition stopping: any, do: :clean_threads
|
104
104
|
|
105
|
-
after_transition any => :starting, :
|
106
|
-
after_transition any => :stopping, :
|
107
|
-
after_transition any => :restarting, :
|
105
|
+
after_transition any => :starting, do: :start_process
|
106
|
+
after_transition any => :stopping, do: :stop_process
|
107
|
+
after_transition any => :restarting, do: :restart_process
|
108
108
|
|
109
|
-
after_transition any => any, :
|
109
|
+
after_transition any => any, do: :record_transition
|
110
110
|
end
|
111
111
|
|
112
112
|
def initialize(process_name, checks, options = {})
|
@@ -207,11 +207,11 @@ module Bluepill
|
|
207
207
|
|
208
208
|
# Watch related methods
|
209
209
|
def add_watch(name, options = {})
|
210
|
-
watches << ConditionWatch.new(name, options.merge(:
|
210
|
+
watches << ConditionWatch.new(name, options.merge(logger: logger))
|
211
211
|
end
|
212
212
|
|
213
213
|
def add_trigger(name, options = {})
|
214
|
-
triggers << Trigger[name].new(self, options.merge(:
|
214
|
+
triggers << Trigger[name].new(self, options.merge(logger: logger))
|
215
215
|
end
|
216
216
|
|
217
217
|
def run_watches
|
@@ -223,15 +223,13 @@ module Bluepill
|
|
223
223
|
|
224
224
|
@transitioned = false
|
225
225
|
|
226
|
-
threads.
|
226
|
+
threads.each_with_object([]) do |(watch, thread), events|
|
227
227
|
thread.join
|
228
|
-
if thread[:events].size
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
end
|
228
|
+
next if thread[:events].size.zero?
|
229
|
+
logger.info "#{watch.name} dispatched: #{thread[:events].join(',')}"
|
230
|
+
thread[:events].each do |event|
|
231
|
+
events << [event, watch.to_s]
|
233
232
|
end
|
234
|
-
events
|
235
233
|
end.each do |event, reason| # rubocop:disable Style/MultilineBlockChain
|
236
234
|
break if @transitioned
|
237
235
|
self.dispatch!(event, reason)
|
@@ -493,16 +491,16 @@ module Bluepill
|
|
493
491
|
|
494
492
|
def system_command_options
|
495
493
|
{
|
496
|
-
:
|
497
|
-
:
|
498
|
-
:
|
499
|
-
:
|
500
|
-
:
|
501
|
-
:
|
502
|
-
:
|
503
|
-
:
|
504
|
-
:
|
505
|
-
:
|
494
|
+
uid: uid,
|
495
|
+
gid: gid,
|
496
|
+
working_dir: working_dir,
|
497
|
+
environment: environment,
|
498
|
+
pid_file: pid_file,
|
499
|
+
logger: logger,
|
500
|
+
stdin: stdin,
|
501
|
+
stdout: stdout,
|
502
|
+
stderr: stderr,
|
503
|
+
supplementary_groups: supplementary_groups,
|
506
504
|
}
|
507
505
|
end
|
508
506
|
|
@@ -2,7 +2,7 @@ module Bluepill
|
|
2
2
|
module ProcessConditions
|
3
3
|
# Process must have cache_actual_pid set to false to function correctly:
|
4
4
|
#
|
5
|
-
# process.checks :zombie_process, :
|
5
|
+
# process.checks :zombie_process, every: 5.seconds
|
6
6
|
# process.cache_actual_pid = false
|
7
7
|
|
8
8
|
class ZombieProcess < ProcessCondition
|
data/lib/bluepill/system.rb
CHANGED
@@ -11,12 +11,12 @@ module Bluepill
|
|
11
11
|
|
12
12
|
# The position of each field in ps output
|
13
13
|
IDX_MAP = {
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
14
|
+
pid: 0,
|
15
|
+
ppid: 1,
|
16
|
+
pcpu: 2,
|
17
|
+
rss: 3,
|
18
|
+
etime: 4,
|
19
|
+
command: 5,
|
20
20
|
}
|
21
21
|
|
22
22
|
def pid_alive?(pid)
|
@@ -142,7 +142,7 @@ module Bluepill
|
|
142
142
|
|
143
143
|
::Process.waitpid(child)
|
144
144
|
|
145
|
-
cmd_status.strip != '' ? Marshal.load(cmd_status) : {:
|
145
|
+
cmd_status.strip != '' ? Marshal.load(cmd_status) : {exit_code: 0, stdout: '', stderr: ''}
|
146
146
|
else
|
147
147
|
# child
|
148
148
|
rd.close
|
@@ -195,9 +195,9 @@ module Bluepill
|
|
195
195
|
|
196
196
|
# collect stdout, stderr and exitcode
|
197
197
|
result = {
|
198
|
-
:
|
199
|
-
:
|
200
|
-
:
|
198
|
+
stdout: cmd_out_read.read,
|
199
|
+
stderr: cmd_err_read.read,
|
200
|
+
exit_code: $CHILD_STATUS.exitstatus,
|
201
201
|
}
|
202
202
|
|
203
203
|
# We're done with these ends of the pipes as well
|
@@ -226,14 +226,13 @@ module Bluepill
|
|
226
226
|
# BSD style ps invocation
|
227
227
|
lines = `ps axo pid,ppid,pcpu,rss,etime,command`.split("\n")
|
228
228
|
|
229
|
-
lines.
|
229
|
+
lines.each_with_object({}) do |line, mem|
|
230
230
|
chunks = line.split(/\s+/)
|
231
231
|
chunks.delete_if { |c| c.strip.empty? }
|
232
232
|
pid = chunks[IDX_MAP[:pid]].strip.to_i
|
233
233
|
command = chunks.slice!(IDX_MAP[:command], chunks.length).join ' '
|
234
234
|
chunks[IDX_MAP[:command]] = command
|
235
235
|
mem[pid] = chunks.flatten
|
236
|
-
mem
|
237
236
|
end
|
238
237
|
end
|
239
238
|
end
|
@@ -9,7 +9,7 @@ module Bluepill
|
|
9
9
|
attr_reader :timeline
|
10
10
|
|
11
11
|
def initialize(process, options = {})
|
12
|
-
options.reverse_merge!(:
|
12
|
+
options.reverse_merge!(times: 5, within: 1, retry_in: 5)
|
13
13
|
|
14
14
|
options.each_pair do |name, val|
|
15
15
|
instance_variable_set("@#{name}", val) if PARAMS.include?(name)
|
data/lib/bluepill/version.rb
CHANGED
@@ -9,12 +9,12 @@ module Bluepill
|
|
9
9
|
|
10
10
|
# @return [Integer]
|
11
11
|
def minor
|
12
|
-
|
12
|
+
1
|
13
13
|
end
|
14
14
|
|
15
15
|
# @return [Integer]
|
16
16
|
def patch
|
17
|
-
|
17
|
+
1
|
18
18
|
end
|
19
19
|
|
20
20
|
# @return [Integer, NilClass]
|
@@ -25,10 +25,10 @@ module Bluepill
|
|
25
25
|
# @return [Hash]
|
26
26
|
def to_h
|
27
27
|
{
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
28
|
+
major: major,
|
29
|
+
minor: minor,
|
30
|
+
patch: patch,
|
31
|
+
pre: pre,
|
32
32
|
}
|
33
33
|
end
|
34
34
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bluepill
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arya Asemanfar
|
@@ -137,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
137
137
|
requirements:
|
138
138
|
- - ">="
|
139
139
|
- !ruby/object:Gem::Version
|
140
|
-
version:
|
140
|
+
version: 1.9.3
|
141
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - ">="
|