unicorn-ctl 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 -13
- data/CHANGELOG.md +6 -1
- data/bin/unicornctl +75 -7
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
OTE3OTY0ZDM3NmNlMTIxMTA2MjczZjBhM2VkMmYzYWUwMjc2Yjg4MA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 99271b94461638a70498a24de7dffe38ef228022
|
4
|
+
data.tar.gz: 935d288070fd63c99bb7f9ea8f79ef3bacee5405
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MmQwZDY5YzFiZDMzOWMxOWNhMTIxZjY2ZGRmZGNjMmQ0M2FiOGY5ZWE0MWRj
|
11
|
-
ZDY4ZjhiZGJlZWM1ZjM2Y2FlZmQyMTY0NmM1OTliNDNmYmY5NDk=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NTY0MmJiNWU1YjM4MDE1NjJkNzY1OWM3ODdiOGYzYzJmOTA3MDU2M2Y0OWQx
|
14
|
-
ZGE5ODc3MWRjZGIxNGU4NmFhNjUwMjgzMTk0NWYzYjk2NTgwMWQ4OTY1NWZi
|
15
|
-
N2FlMWNiYjI5MWJkYjEzYTJlNTQ2OTJmMTdiMWU5MTUwNTY3NGM=
|
6
|
+
metadata.gz: 0dad00539469ef82c81a22be57c0eb49640483dfaea77ab004f63f32bd98710a1be5617396d101c7b70d5c73fe58eb80f3d439687d1c4980c212a34ce4d57d72
|
7
|
+
data.tar.gz: 14856718dbd85f76bd13e195ff523aacbf677308695021f70afc8fc6b0cdc5ce84352ddec1e57a77de916a8de779348c7184ac19db072daaef6cabaa371d89e0
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
## UnicornCtl Changelog
|
2
2
|
|
3
|
-
### 0.1.
|
3
|
+
### 0.1.4 / 2014-02-20
|
4
|
+
|
5
|
+
* Add a wait period after upgrade/start to make sure new master has a chance to start before we perform a health check on it.
|
6
|
+
* Add an option for the script to watch new master process until its proctitle changes.
|
7
|
+
|
8
|
+
### 0.1.3 / 2013-09-17
|
4
9
|
|
5
10
|
* Fix unicorn upgrades: really wait for the new master to replace the old one.
|
6
11
|
|
data/bin/unicornctl
CHANGED
@@ -60,6 +60,15 @@ def escape(param)
|
|
60
60
|
Shellwords.escape(param)
|
61
61
|
end
|
62
62
|
|
63
|
+
def wait_with_timeout(timeout, sleep_time = 1, &block)
|
64
|
+
raise "No block given" unless block_given?
|
65
|
+
start_time = Time.now
|
66
|
+
while Time.now - start_time < timeout do
|
67
|
+
block.call
|
68
|
+
sleep(sleep_time)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
63
72
|
#-------------------------------------------------------------------------------------------
|
64
73
|
# Check if process is still running
|
65
74
|
def pid_running?(pid)
|
@@ -85,11 +94,9 @@ end
|
|
85
94
|
|
86
95
|
def wait_for_pid_to_die(pid, timeout)
|
87
96
|
print "Waiting for the process to stop: "
|
88
|
-
|
89
|
-
while Time.now - start_time < timeout
|
97
|
+
wait_with_timeout(timeout) do
|
90
98
|
print "."
|
91
99
|
break unless pid_running?(pid)
|
92
|
-
sleep(1)
|
93
100
|
end
|
94
101
|
end
|
95
102
|
|
@@ -108,6 +115,13 @@ def stop_unicorn_process(pid, timeout, graceful)
|
|
108
115
|
end
|
109
116
|
end
|
110
117
|
|
118
|
+
def process_title(pid)
|
119
|
+
return nil unless pid_running?(pid)
|
120
|
+
cmdline_file = "/proc/#{pid}/cmdline"
|
121
|
+
return nil unless File.readable?(cmdline_file)
|
122
|
+
return File.read(cmdline_file).strip
|
123
|
+
end
|
124
|
+
|
111
125
|
#---------------------------------------------------------------------------------------------------
|
112
126
|
# Kills a process and all of its descendants
|
113
127
|
def kill_tree(pid)
|
@@ -218,6 +232,12 @@ def start_application!(options)
|
|
218
232
|
exit(1)
|
219
233
|
end
|
220
234
|
|
235
|
+
# Wait for a while to let the new master start
|
236
|
+
if options[:start_wait] > 0
|
237
|
+
puts "Waiting for #{options[:start_wait]} seconds to let the new master load completely..."
|
238
|
+
sleep(options[:start_wait])
|
239
|
+
end
|
240
|
+
|
221
241
|
# If we have a health check url, let's check it
|
222
242
|
if options[:check_url]
|
223
243
|
exit(1) unless check_app_health(options)
|
@@ -313,10 +333,8 @@ def upgrade_application!(options)
|
|
313
333
|
puts "Waiting for the new master to replace the old one..."
|
314
334
|
|
315
335
|
# Wait for the new master to start
|
316
|
-
start_time = Time.now
|
317
336
|
new_started = false
|
318
|
-
|
319
|
-
sleep(1)
|
337
|
+
wait_with_timeout(options[:timeout]) do
|
320
338
|
new_pid = File.exists?(pid_file) ? read_pid(pid_file) : nil
|
321
339
|
if new_pid && new_pid != old_pid
|
322
340
|
new_started = true
|
@@ -335,6 +353,30 @@ def upgrade_application!(options)
|
|
335
353
|
new_pid = read_pid(pid_file)
|
336
354
|
puts "New master detected with pid=#{new_pid}"
|
337
355
|
|
356
|
+
# Just in case we were asked to watch master proctitle, save its current content
|
357
|
+
master_proctitle = process_title(new_pid)
|
358
|
+
if options[:watch_proctitle]
|
359
|
+
puts "New master process #{new_pid} title: #{master_proctitle}"
|
360
|
+
end
|
361
|
+
|
362
|
+
# Wait for a while to let the new master start
|
363
|
+
if options[:start_wait] > 0
|
364
|
+
puts "Waiting for #{options[:start_wait]} seconds to let the new master load completely..."
|
365
|
+
sleep(options[:start_wait])
|
366
|
+
end
|
367
|
+
|
368
|
+
# If we're asked to watch proctitle, let's wait for the title to change
|
369
|
+
if options[:watch_proctitle]
|
370
|
+
puts "Waiting for process title to change for master process #{new_pid}..."
|
371
|
+
wait_with_timeout(options[:timeout]) do
|
372
|
+
cur_title = process_title(new_pid)
|
373
|
+
if master_proctitle != cur_title
|
374
|
+
puts "Master process #{new_pid} new title: #{cur_title}"
|
375
|
+
break
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
338
380
|
# If we have a health check url, let's check it
|
339
381
|
if options[:check_url]
|
340
382
|
if check_app_health(options)
|
@@ -351,6 +393,15 @@ def upgrade_application!(options)
|
|
351
393
|
puts "Stopping old unicorn master: #{old_pid}"
|
352
394
|
stop_unicorn_process(old_pid, options[:timeout], true)
|
353
395
|
|
396
|
+
# If we have a health check url, let's pefrorm the final check
|
397
|
+
if options[:check_url]
|
398
|
+
puts "Performing the final health check..."
|
399
|
+
unless check_app_health(options)
|
400
|
+
puts "ERROR: Final health check failed!"
|
401
|
+
exit(1)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
354
405
|
# All done!
|
355
406
|
puts "OK: Upgrade is done successfully!"
|
356
407
|
end
|
@@ -409,10 +460,12 @@ def show_help(error = nil)
|
|
409
460
|
puts ' --health-check-url=url | -H url Health check URL used to make sure the app has started'
|
410
461
|
puts ' --health-check-content=string | -C string Health check expected content (default: just check for HTTP 200 OK)'
|
411
462
|
puts ' --health-check-timeout=sec | -T sec Individual health check timeout (default: 5 sec)'
|
463
|
+
puts ' --start-wait=sec | -w sec New master startup wait (default: 5 sec, use 0 to disable)'
|
412
464
|
puts ' --timeout=sec | -t sec Operation (start/stop/etc) timeout (default: 30 sec)'
|
413
465
|
puts ' --unicorn-config=file | -c file Unicorn config file to use, absolute or relative path (default: shared/unicorn.rb)'
|
414
466
|
puts ' --rackup-config=file | -r file Rackup config file to use, absolute or relative path (default: current/config.ru)'
|
415
467
|
puts ' --pid-file=file | -p file PID-file unicorn is configured to use (default: shared/pids/unicorn.pid)'
|
468
|
+
puts ' --watch-proctitle | -W Watch new master proctitle until it changes, which usually means it has finished loading'
|
416
469
|
puts ' --rainbows | -R Use rainbows to start the app (default: use unicorn)'
|
417
470
|
puts ' --help | -h This help'
|
418
471
|
puts
|
@@ -427,10 +480,12 @@ opts = GetoptLong.new(
|
|
427
480
|
[ '--health-check-url', '-U', GetoptLong::REQUIRED_ARGUMENT ],
|
428
481
|
[ '--health-check-content', '-C', GetoptLong::REQUIRED_ARGUMENT ],
|
429
482
|
[ '--health-check-timeout', '-T', GetoptLong::REQUIRED_ARGUMENT ],
|
483
|
+
[ '--start-wait', '-w', GetoptLong::REQUIRED_ARGUMENT ],
|
430
484
|
[ '--timeout', '-t', GetoptLong::REQUIRED_ARGUMENT ],
|
431
485
|
[ '--unicorn-config=file', '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
432
486
|
[ '--rackup-config=file', '-r', GetoptLong::REQUIRED_ARGUMENT ],
|
433
487
|
[ '--pid-file=file', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
488
|
+
[ '--watch-proctitle', '-W', GetoptLong::NO_ARGUMENT ],
|
434
489
|
[ '--rainbows', '-R', GetoptLong::NO_ARGUMENT ],
|
435
490
|
[ '--help', '-h', GetoptLong::NO_ARGUMENT ]
|
436
491
|
)
|
@@ -443,10 +498,12 @@ options = {
|
|
443
498
|
:env => 'development',
|
444
499
|
:timeout => 30,
|
445
500
|
:check_timeout => 5,
|
501
|
+
:start_wait => 5,
|
446
502
|
:unicorn_bin => 'unicorn',
|
447
503
|
:pid_file => nil,
|
448
504
|
:rackup_config => nil,
|
449
|
-
:unicorn_config => nil
|
505
|
+
:unicorn_config => nil,
|
506
|
+
:watch_proctitle => false
|
450
507
|
}
|
451
508
|
|
452
509
|
# Process options
|
@@ -470,6 +527,9 @@ opts.each do |opt, arg|
|
|
470
527
|
when "--health-check-timeout"
|
471
528
|
options[:check_timeout] = arg.to_i
|
472
529
|
|
530
|
+
when "--start-wait"
|
531
|
+
options[:start_wait] = arg.to_i
|
532
|
+
|
473
533
|
when "--unicorn-config"
|
474
534
|
options[:unicorn_config] = arg.strip
|
475
535
|
|
@@ -479,6 +539,14 @@ opts.each do |opt, arg|
|
|
479
539
|
when "--pid-file"
|
480
540
|
options[:pid_file] = arg.strip
|
481
541
|
|
542
|
+
when "--watch-proctitle"
|
543
|
+
# Try to get pid for self
|
544
|
+
if process_title(Process.pid)
|
545
|
+
options[:watch_proctitle] = true
|
546
|
+
else
|
547
|
+
puts "WARNING: Proctitle checking is not supported on this platform!"
|
548
|
+
end
|
549
|
+
|
482
550
|
when "--rainbows"
|
483
551
|
options[:unicorn_bin] = 'rainbows'
|
484
552
|
|
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn-ctl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleksiy Kovyrin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
description: A script to control unicorn instances.
|
@@ -46,10 +46,10 @@ executables:
|
|
46
46
|
extensions: []
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
|
-
- bin/unicornctl
|
50
|
-
- LICENSE.txt
|
51
49
|
- CHANGELOG.md
|
50
|
+
- LICENSE.txt
|
52
51
|
- README.md
|
52
|
+
- bin/unicornctl
|
53
53
|
homepage: https://github.com/swiftype/unicorn-ctl
|
54
54
|
licenses:
|
55
55
|
- MIT
|
@@ -60,17 +60,17 @@ require_paths:
|
|
60
60
|
- lib
|
61
61
|
required_ruby_version: !ruby/object:Gem::Requirement
|
62
62
|
requirements:
|
63
|
-
- -
|
63
|
+
- - ">="
|
64
64
|
- !ruby/object:Gem::Version
|
65
65
|
version: '0'
|
66
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
|
-
- -
|
68
|
+
- - ">="
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '0'
|
71
71
|
requirements: []
|
72
72
|
rubyforge_project:
|
73
|
-
rubygems_version: 2.
|
73
|
+
rubygems_version: 2.2.0
|
74
74
|
signing_key:
|
75
75
|
specification_version: 4
|
76
76
|
summary: Start/stop/restart/upgrade unicorn instances reliably.
|