bluepill 0.1.3 → 0.1.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 +5 -5
- data/CHANGELOG.md +820 -0
- data/CONTRIBUTING.md +31 -0
- data/LICENSE +1 -1
- data/README.md +64 -29
- data/bin/bluepill +1 -1
- data/bluepill.gemspec +17 -6
- data/lib/bluepill/application.rb +309 -41
- data/lib/bluepill/condition_watch.rb +103 -8
- data/lib/bluepill/controller.rb +124 -13
- data/lib/bluepill/dsl/app_proxy.rb +102 -3
- data/lib/bluepill/dsl/process_factory.rb +183 -60
- data/lib/bluepill/dsl/process_proxy.rb +132 -14
- data/lib/bluepill/dsl.rb +27 -5
- data/lib/bluepill/group.rb +142 -9
- data/lib/bluepill/logger.rb +120 -5
- data/lib/bluepill/process.rb +571 -200
- data/lib/bluepill/process_commands.rb +262 -0
- data/lib/bluepill/process_conditions/always_true.rb +18 -4
- data/lib/bluepill/process_conditions/cpu_usage.rb +34 -0
- data/lib/bluepill/process_conditions/file_time.rb +40 -4
- data/lib/bluepill/process_conditions/http.rb +81 -23
- data/lib/bluepill/process_conditions/mem_usage.rb +61 -2
- data/lib/bluepill/process_conditions/process_condition.rb +43 -0
- data/lib/bluepill/process_conditions/running_time.rb +36 -1
- data/lib/bluepill/process_conditions/zombie_process.rb +26 -5
- data/lib/bluepill/process_conditions.rb +15 -1
- data/lib/bluepill/process_journal.rb +256 -104
- data/lib/bluepill/process_statistics.rb +33 -3
- data/lib/bluepill/socket.rb +63 -16
- data/lib/bluepill/system/commands.rb +286 -0
- data/lib/bluepill/system.rb +192 -228
- data/lib/bluepill/trigger.rb +110 -14
- data/lib/bluepill/triggers/flapping.rb +84 -3
- data/lib/bluepill/util/rotational_array.rb +24 -1
- data/lib/bluepill/version.rb +71 -19
- data/lib/bluepill.rb +25 -2
- data/sig/bluepill.rbs +926 -0
- data/sig/manifest.yaml +7 -0
- metadata +16 -34
- data/bin/sample_forking_server +0 -66
- data/lib/bluepill/application/client.rb +0 -6
- data/lib/bluepill/application/server.rb +0 -21
data/CONTRIBUTING.md
CHANGED
|
@@ -4,3 +4,34 @@ Contributing
|
|
|
4
4
|
To ease development and troubleshooting, a simple vagrant environment exists [here](https://github.com/iancoffey/chef_bluepill_devel). A "vagrant up" should do the trick.
|
|
5
5
|
|
|
6
6
|
As more OS options are added, this should also simplify the steps necessary to reproduce odd issues.
|
|
7
|
+
|
|
8
|
+
Type checking
|
|
9
|
+
-------------
|
|
10
|
+
|
|
11
|
+
The RBS signatures in `sig/bluepill.rbs` ship with the gem, and CI checks `lib` against them with [Steep](https://github.com/soutaro/steep) in strict mode. Steep needs Ruby 3.3 or newer. To run the check locally:
|
|
12
|
+
|
|
13
|
+
bundle exec rake steep
|
|
14
|
+
|
|
15
|
+
This installs the signatures of the dependencies into `.gem_rbs_collection`, validates the signatures and runs `steep check`. `sig-vendor` has stubs for the dependencies that publish no signatures. Update `sig/bluepill.rbs` when you change a method in `lib`.
|
|
16
|
+
|
|
17
|
+
Mutation testing
|
|
18
|
+
----------------
|
|
19
|
+
|
|
20
|
+
CI runs [mutant](https://github.com/mbj/mutant) on Ruby 4.0, and every mutant must be killed. Mutant needs Ruby 3.3 or newer. To run it on every subject locally:
|
|
21
|
+
|
|
22
|
+
bundle exec rake mutant
|
|
23
|
+
|
|
24
|
+
Or only on the subjects you changed since `master`:
|
|
25
|
+
|
|
26
|
+
bundle exec mutant run --since master
|
|
27
|
+
|
|
28
|
+
CI only mutates the subjects that a push or pull request changes, split into shards that run in parallel. To mutate every subject in CI, run the Mutant workflow from the Actions tab.
|
|
29
|
+
|
|
30
|
+
Performance
|
|
31
|
+
-----------
|
|
32
|
+
|
|
33
|
+
[Duel](https://github.com/sferik/duel-ruby) guards against changes that make bluepill slower. The benchmarks in `duel/` cover what bluepill does every tick: parsing `ps`, finding children, running checks, ticking processes, and logging. Duel needs Ruby 3.4 or newer. To compare your branch with `master`:
|
|
34
|
+
|
|
35
|
+
bundle exec duel
|
|
36
|
+
|
|
37
|
+
A pull request that makes a benchmark slower, allocate more, or leave more objects alive fails the Perf workflow. To check that new benchmarks pass on unchanged code, run `bundle exec duel --force`, and to run some of them, add `--filter "^watch:"`.
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
# Bluepill
|
|
2
2
|
Bluepill is a simple process monitoring tool written in Ruby.
|
|
3
3
|
|
|
4
|
+
[](https://github.com/sferik/duel-ruby)
|
|
5
|
+
[][test]
|
|
6
|
+
[][lint]
|
|
7
|
+
[][mutant]
|
|
8
|
+
[][qlty]
|
|
9
|
+
[][coveralls]
|
|
4
10
|
[][gem]
|
|
5
|
-
[][travis]
|
|
6
|
-
[][gemnasium]
|
|
7
|
-
[][codeclimate]
|
|
8
|
-
[][coveralls]
|
|
9
11
|
|
|
10
12
|
[gem]: https://rubygems.org/gems/bluepill
|
|
11
|
-
[
|
|
12
|
-
[
|
|
13
|
-
[
|
|
13
|
+
[test]: https://github.com/bluepill-rb/bluepill/actions/workflows/test.yml
|
|
14
|
+
[lint]: https://github.com/bluepill-rb/bluepill/actions/workflows/lint.yml
|
|
15
|
+
[mutant]: https://github.com/bluepill-rb/bluepill/actions/workflows/mutant.yml
|
|
16
|
+
[qlty]: https://qlty.sh/gh/bluepill-rb/projects/bluepill
|
|
14
17
|
[coveralls]: https://coveralls.io/github/bluepill-rb/bluepill?branch=master
|
|
15
18
|
|
|
16
19
|
## Installation
|
|
@@ -80,7 +83,7 @@ Bluepill.application("app_name") do |app|
|
|
|
80
83
|
process.checks :mem_usage, every: 10.seconds, below: 100.megabytes, times: [3,5]
|
|
81
84
|
end
|
|
82
85
|
end
|
|
83
|
-
|
|
86
|
+
```
|
|
84
87
|
|
|
85
88
|
To watch the modification time of a file, e.g. a log file to ensure the process is actually working add one more line:
|
|
86
89
|
|
|
@@ -225,6 +228,20 @@ end
|
|
|
225
228
|
|
|
226
229
|
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.
|
|
227
230
|
|
|
231
|
+
To run a command before every start, for example to clear a cache:
|
|
232
|
+
|
|
233
|
+
```ruby
|
|
234
|
+
Bluepill.application("app_name") do |app|
|
|
235
|
+
app.process("process_name") do |process|
|
|
236
|
+
process.pre_start_command = "/usr/bin/some_setup_command"
|
|
237
|
+
process.start_command = "/usr/bin/some_start_command"
|
|
238
|
+
process.pid_file = "/tmp/some_pid_file.pid"
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Bluepill waits for the `pre_start_command` to finish, and logs a warning if it exits with a non-zero status, but starts the process either way. It runs in the same `working_dir`, with the same `environment`, `uid`, and `gid`, as the process.
|
|
244
|
+
|
|
228
245
|
By default, bluepill will send a SIGTERM to your process when stopping.
|
|
229
246
|
To change the stop command:
|
|
230
247
|
|
|
@@ -264,35 +281,34 @@ process.monitor_children do |child_process|
|
|
|
264
281
|
end
|
|
265
282
|
```
|
|
266
283
|
|
|
267
|
-
Note {{PID}} will be substituted for the pid of process in both the stop and restart commands.
|
|
284
|
+
Note `{{PID}}` will be substituted for the pid of process in both the stop and restart commands.
|
|
268
285
|
|
|
269
|
-
###
|
|
286
|
+
### Commands Don't Run in a Shell
|
|
270
287
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
```ruby
|
|
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
|
|
280
|
-
```
|
|
288
|
+
Bluepill splits each command (`start_command`, `pre_start_command`, `stop_command`, and `restart_command`) into words and runs it directly, without a shell. So shell syntax like `cd ... &&`, `VAR=value`, `|`, `>`, `2>&1`, and `*` globs doesn't work.
|
|
281
289
|
|
|
282
|
-
|
|
290
|
+
Use the config options instead:
|
|
283
291
|
|
|
284
292
|
```ruby
|
|
285
293
|
Bluepill.application("app_name") do |app|
|
|
286
294
|
app.process("process_name") do |process|
|
|
287
|
-
process.start_command = "/usr/bin/
|
|
295
|
+
process.start_command = "/usr/bin/some_start_command"
|
|
288
296
|
process.working_dir = "/tmp/some_dir"
|
|
297
|
+
process.environment = {"SOME_VAR" => "1"}
|
|
289
298
|
process.stdout = process.stderr = "/tmp/server.log"
|
|
290
299
|
process.pid_file = "/tmp/some_pid_file.pid"
|
|
300
|
+
process.daemonize = true
|
|
291
301
|
end
|
|
292
302
|
end
|
|
293
303
|
```
|
|
294
304
|
|
|
295
|
-
|
|
305
|
+
`stdout`, `stderr`, and `stdin` only apply to processes that bluepill daemonizes. A daemonized process starts in `/` unless you set `working_dir`, so use absolute paths or set `working_dir`.
|
|
306
|
+
|
|
307
|
+
If you really need a shell, run one explicitly, and use `exec` so bluepill monitors your server instead of the shell that started it:
|
|
308
|
+
|
|
309
|
+
```ruby
|
|
310
|
+
process.start_command = "sh -c 'exec /usr/bin/some_start_command < /tmp/input'"
|
|
311
|
+
```
|
|
296
312
|
|
|
297
313
|
### CLI
|
|
298
314
|
|
|
@@ -331,6 +347,24 @@ To quit the bluepill daemon for an application:
|
|
|
331
347
|
|
|
332
348
|
sudo bluepill quit
|
|
333
349
|
|
|
350
|
+
#### bpsv
|
|
351
|
+
|
|
352
|
+
`bpsv` runs a bluepill command on the process it's named after, so a
|
|
353
|
+
symlink to it works like an init script. For a process named `unicorn`:
|
|
354
|
+
|
|
355
|
+
sudo ln -s "$(which bpsv)" /usr/local/bin/unicorn
|
|
356
|
+
sudo unicorn restart
|
|
357
|
+
|
|
358
|
+
That runs `bluepill restart unicorn`. Like `bluepill` without an
|
|
359
|
+
_app_name_, it only works when one bluepill daemon is running.
|
|
360
|
+
|
|
361
|
+
### Examples
|
|
362
|
+
|
|
363
|
+
[examples/sample_app.rb](examples/sample_app.rb) monitors a small forking
|
|
364
|
+
echo server, and stops any worker that uses too much memory. Its comments
|
|
365
|
+
show how to run it. [examples/runit.rb](examples/runit.rb) monitors a
|
|
366
|
+
service managed by runit.
|
|
367
|
+
|
|
334
368
|
### Logging
|
|
335
369
|
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:
|
|
336
370
|
|
|
@@ -355,7 +389,7 @@ end
|
|
|
355
389
|
Note that You must define only one application per config when using foreground mode.
|
|
356
390
|
|
|
357
391
|
|
|
358
|
-
|
|
392
|
+
JRuby allows you to run bluepill only in the foreground.
|
|
359
393
|
|
|
360
394
|
## Links
|
|
361
395
|
|
|
@@ -366,15 +400,16 @@ y allows you to run bluepill only in the foreground.
|
|
|
366
400
|
[rubygems]: http://rubygems.org/gems/bluepill
|
|
367
401
|
|
|
368
402
|
## Supported Ruby Versions
|
|
369
|
-
This library aims to support and is [tested against][
|
|
403
|
+
This library aims to support and is [tested against][ci] the following Ruby
|
|
370
404
|
implementations:
|
|
371
405
|
|
|
372
406
|
* Ruby 1.9.3
|
|
373
|
-
* Ruby 2.0.
|
|
374
|
-
* Ruby
|
|
375
|
-
* Ruby
|
|
407
|
+
* Ruby 2.0 through 2.7
|
|
408
|
+
* Ruby 3.0 through 3.4
|
|
409
|
+
* Ruby 4.0
|
|
376
410
|
* JRuby 1.7 (only in the foreground)
|
|
377
|
-
* JRuby 9.0.
|
|
411
|
+
* JRuby 9.0 through 9.4 (only in the foreground)
|
|
412
|
+
* JRuby 10.0 and 10.1 (only in the foreground)
|
|
378
413
|
|
|
379
414
|
If something doesn't work on one of these interpreters, please open an issue.
|
|
380
415
|
|
data/bin/bluepill
CHANGED
|
@@ -72,7 +72,7 @@ if options[:privileged] && ::Process.euid != 0
|
|
|
72
72
|
exit(3)
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
-
APPLICATION_COMMANDS = %w
|
|
75
|
+
APPLICATION_COMMANDS = %w[status start stop restart unmonitor quit log].freeze
|
|
76
76
|
|
|
77
77
|
controller = Bluepill::Controller.new(options.slice(:base_dir, :log_file))
|
|
78
78
|
|
data/bluepill.gemspec
CHANGED
|
@@ -6,21 +6,32 @@ Gem::Specification.new do |spec|
|
|
|
6
6
|
spec.name = 'bluepill'
|
|
7
7
|
spec.version = Bluepill::Version
|
|
8
8
|
spec.platform = Gem::Platform::RUBY
|
|
9
|
-
spec.authors = ['Arya Asemanfar', '
|
|
9
|
+
spec.authors = ['Arya Asemanfar', 'Erik Berlin', 'Rohith Ravi', 'Gary Tsang']
|
|
10
10
|
spec.email = ['entombedvirus@gmail.com']
|
|
11
|
-
spec.homepage = '
|
|
11
|
+
spec.homepage = 'https://github.com/bluepill-rb/bluepill'
|
|
12
12
|
spec.summary = 'A process monitor written in Ruby with stability and minimalism in mind.'
|
|
13
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
14
|
spec.license = 'MIT'
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
# RubyGems before 2.0, which Ruby 1.9.3 ships with, has no metadata
|
|
17
|
+
if spec.respond_to?(:metadata=)
|
|
18
|
+
spec.metadata = {
|
|
19
|
+
'source_code_uri' => 'https://github.com/bluepill-rb/bluepill',
|
|
20
|
+
'changelog_uri' => 'https://github.com/bluepill-rb/bluepill/blob/master/CHANGELOG.md',
|
|
21
|
+
'bug_tracker_uri' => 'https://github.com/bluepill-rb/bluepill/issues',
|
|
22
|
+
'rubygems_mfa_required' => 'true',
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
spec.add_dependency 'activesupport', '>= 3.2'
|
|
17
27
|
spec.add_dependency 'blue-daemons', '~> 1.1'
|
|
18
28
|
spec.add_dependency 'state_machine', '~> 1.1'
|
|
19
|
-
spec.add_development_dependency 'bundler', '~> 1.3'
|
|
20
29
|
|
|
21
30
|
spec.required_ruby_version = '>= 1.9.3'
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
spec.executables =
|
|
32
|
+
# sig has the RBS signatures, and the standard libraries they use in manifest.yaml
|
|
33
|
+
spec.executables = %w[bluepill bpsv]
|
|
34
|
+
spec.files = %w[CHANGELOG.md CONTRIBUTING.md DESIGN.md LICENSE README.md bluepill.gemspec sig/manifest.yaml] +
|
|
35
|
+
spec.executables.collect { |f| "bin/#{f}" } + Dir['lib/**/*.rb'] + Dir['sig/**/*.rbs']
|
|
25
36
|
spec.require_paths = ['lib']
|
|
26
37
|
end
|