bluepill 0.1.2 → 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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +820 -0
  3. data/CONTRIBUTING.md +31 -0
  4. data/LICENSE +1 -1
  5. data/README.md +69 -30
  6. data/bin/bluepill +2 -2
  7. data/bluepill.gemspec +17 -6
  8. data/lib/bluepill/application.rb +311 -43
  9. data/lib/bluepill/condition_watch.rb +105 -10
  10. data/lib/bluepill/controller.rb +125 -14
  11. data/lib/bluepill/dsl/app_proxy.rb +103 -4
  12. data/lib/bluepill/dsl/process_factory.rb +185 -62
  13. data/lib/bluepill/dsl/process_proxy.rb +132 -14
  14. data/lib/bluepill/dsl.rb +27 -5
  15. data/lib/bluepill/group.rb +142 -9
  16. data/lib/bluepill/logger.rb +122 -7
  17. data/lib/bluepill/process.rb +582 -211
  18. data/lib/bluepill/process_commands.rb +262 -0
  19. data/lib/bluepill/process_conditions/always_true.rb +18 -4
  20. data/lib/bluepill/process_conditions/cpu_usage.rb +34 -0
  21. data/lib/bluepill/process_conditions/file_time.rb +40 -4
  22. data/lib/bluepill/process_conditions/http.rb +81 -23
  23. data/lib/bluepill/process_conditions/mem_usage.rb +64 -5
  24. data/lib/bluepill/process_conditions/process_condition.rb +45 -2
  25. data/lib/bluepill/process_conditions/running_time.rb +36 -1
  26. data/lib/bluepill/process_conditions/zombie_process.rb +26 -5
  27. data/lib/bluepill/process_conditions.rb +15 -1
  28. data/lib/bluepill/process_journal.rb +256 -104
  29. data/lib/bluepill/process_statistics.rb +33 -3
  30. data/lib/bluepill/socket.rb +63 -16
  31. data/lib/bluepill/system/commands.rb +286 -0
  32. data/lib/bluepill/system.rb +193 -229
  33. data/lib/bluepill/trigger.rb +111 -15
  34. data/lib/bluepill/triggers/flapping.rb +86 -5
  35. data/lib/bluepill/util/rotational_array.rb +25 -2
  36. data/lib/bluepill/version.rb +71 -19
  37. data/lib/bluepill.rb +25 -2
  38. data/sig/bluepill.rbs +926 -0
  39. data/sig/manifest.yaml +7 -0
  40. metadata +16 -35
  41. data/bin/sample_forking_server +0 -66
  42. data/lib/bluepill/application/client.rb +0 -6
  43. 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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Arya Asemanfar, Rohith Ravi, Gary Tsang
1
+ Copyright (c) 2009-2026 Arya Asemanfar, Erik Berlin, Rohith Ravi, Gary Tsang
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person
4
4
  obtaining a copy of this software and associated documentation
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
+ [![Duel](https://raw.githubusercontent.com/sferik/duel-ruby/main/assets/badge.svg)](https://github.com/sferik/duel-ruby)
5
+ [![Test](https://github.com/bluepill-rb/bluepill/actions/workflows/test.yml/badge.svg?branch=master)][test]
6
+ [![Lint](https://github.com/bluepill-rb/bluepill/actions/workflows/lint.yml/badge.svg?branch=master)][lint]
7
+ [![Mutant](https://github.com/bluepill-rb/bluepill/actions/workflows/mutant.yml/badge.svg?branch=master)][mutant]
8
+ [![Maintainability](https://qlty.sh/gh/bluepill-rb/projects/bluepill/maintainability.svg)][qlty]
9
+ [![Coverage Status](https://coveralls.io/repos/github/bluepill-rb/bluepill/badge.svg?branch=master)][coveralls]
4
10
  [![Gem Version](https://badge.fury.io/rb/bluepill.svg)][gem]
5
- [![Build Status](https://travis-ci.org/bluepill-rb/bluepill.svg?branch=master)][travis]
6
- [![Dependency Status](https://gemnasium.com/bluepill-rb/bluepill.svg)][gemnasium]
7
- [![Code Climate](https://codeclimate.com/github/bluepill-rb/bluepill/badges/gpa.svg)][codeclimate]
8
- [![Coverage Status](https://coveralls.io/repos/bluepill-rb/bluepill/badge.svg?branch=master&service=github)][coveralls]
9
11
 
10
12
  [gem]: https://rubygems.org/gems/bluepill
11
- [travis]: https://travis-ci.org/bluepill-rb/bluepill
12
- [gemnasium]: https://gemnasium.com/bluepill-rb/bluepill
13
- [codeclimate]: https://codeclimate.com/github/bluepill-rb/bluepill
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
- ### A Note About Output Redirection
286
+ ### Commands Don't Run in a Shell
270
287
 
271
- While you can specify shell tricks like the following in the `start_command` of a process:
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.
272
289
 
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
- ```
281
-
282
- We recommend that you _not_ do that and instead use the config options to capture output from your daemons. Like so:
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/env SOME_VAR=1 /usr/bin/some_start_command"
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
- 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.
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&apos;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
 
@@ -342,7 +376,8 @@ end
342
376
 
343
377
  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.
344
378
 
345
- ### Extra options
379
+ ### Foreground mode
380
+
346
381
  You can run bluepill in the foreground:
347
382
 
348
383
  ```ruby
@@ -353,6 +388,9 @@ end
353
388
 
354
389
  Note that You must define only one application per config when using foreground mode.
355
390
 
391
+
392
+ JRuby allows you to run bluepill only in the foreground.
393
+
356
394
  ## Links
357
395
 
358
396
  * Code: [http://github.com/bluepill-rb/bluepill](http://github.com/bluepill-rb/bluepill)
@@ -362,15 +400,16 @@ Note that You must define only one application per config when using foreground
362
400
  [rubygems]: http://rubygems.org/gems/bluepill
363
401
 
364
402
  ## Supported Ruby Versions
365
- This library aims to support and is [tested against][travis] the following Ruby
403
+ This library aims to support and is [tested against][ci] the following Ruby
366
404
  implementations:
367
405
 
368
406
  * Ruby 1.9.3
369
- * Ruby 2.0.0
370
- * Ruby 2.1
371
- * Ruby 2.2
372
- * JRuby 1.7
373
- * JRuby 9.0.0.0
407
+ * Ruby 2.0 through 2.7
408
+ * Ruby 3.0 through 3.4
409
+ * Ruby 4.0
410
+ * JRuby 1.7 (only in the foreground)
411
+ * JRuby 9.0 through 9.4 (only in the foreground)
412
+ * JRuby 10.0 and 10.1 (only in the foreground)
374
413
 
375
414
  If something doesn't work on one of these interpreters, please open an issue.
376
415
 
data/bin/bluepill CHANGED
@@ -1,4 +1,4 @@
1
- #! /usr/bin/env ruby
1
+ #!/usr/bin/env ruby
2
2
  require 'optparse'
3
3
  require 'bluepill'
4
4
 
@@ -72,7 +72,7 @@ if options[:privileged] && ::Process.euid != 0
72
72
  exit(3)
73
73
  end
74
74
 
75
- APPLICATION_COMMANDS = %w(status start stop restart unmonitor quit log)
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', 'Gary Tsang', 'Rohith Ravi']
9
+ spec.authors = ['Arya Asemanfar', 'Erik Berlin', 'Rohith Ravi', 'Gary Tsang']
10
10
  spec.email = ['entombedvirus@gmail.com']
11
- spec.homepage = 'http://github.com/bluepill-rb/bluepill'
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
- spec.add_dependency 'activesupport', ['>= 3.2', '< 5']
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
- 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) }
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