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.
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.