unicorn-ctl 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|