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.
Files changed (4) hide show
  1. checksums.yaml +5 -13
  2. data/CHANGELOG.md +6 -1
  3. data/bin/unicornctl +75 -7
  4. metadata +11 -11
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MzBlYWViYjZjZTJlYmE5MzM2NGI1NTUyOTg1Nzc4OGQyN2U1YzM1NA==
5
- data.tar.gz: !binary |-
6
- OTE3OTY0ZDM3NmNlMTIxMTA2MjczZjBhM2VkMmYzYWUwMjc2Yjg4MA==
2
+ SHA1:
3
+ metadata.gz: 99271b94461638a70498a24de7dffe38ef228022
4
+ data.tar.gz: 935d288070fd63c99bb7f9ea8f79ef3bacee5405
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MzJlYmQyMWMyNGY2MGEwODY3NDYzMzk0MGYwNTlkYjJlOGE0ZWVlMmQ3MGQ0
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 / Not released yet
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
- start_time = Time.now
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
- while Time.now - start_time < options[:timeout]
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.3
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: 2013-09-17 00:00:00.000000000 Z
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.1.3
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.