2011-12-29 13 views
9

Được rồi, điều này đang làm tan chảy bộ não của tôi. Nó có thể có một cái gì đó để làm với thực tế là tôi không hiểu Upstart cũng như tôi nên. Xin lỗi trước cho câu hỏi dài.Sử dụng Upstart để quản lý Unicorn w/rbenv + bundler binstubs w/ruby-local-exec shebang

Tôi đang cố gắng sử dụng Upstart để quản lý quy trình tổng thể Unicorn của ứng dụng Rails. Đây là số /etc/init/app.conf hiện tại của tôi:

description "app" 

start on runlevel [2] 
stop on runlevel [016] 

console owner 

# expect daemon 

script 
    APP_ROOT=/home/deploy/app 
    PATH=/home/deploy/.rbenv/shims:/home/deploy/.rbenv/bin:$PATH 
    $APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production # >> /tmp/upstart.log 2>&1 
end script 

# respawn 

Điều đó chỉ hoạt động tốt - Unicorn khởi động tuyệt vời. Điều không tuyệt vời là PID được phát hiện không phải là chủ nhân Unicorn, nó thuộc về quá trình sh. Điều đó trong và của chính nó không phải là xấu như vậy, hoặc - nếu tôi đã không sử dụng chiến lược triển khai tự động Unicorn zero-downtime. Bởi vì ngay sau khi tôi gửi -USR2 cho tổng thể Unicorn của tôi, một tổng thể mới sinh ra và cái cũ chết ... và quá trình sh cũng vậy. Vì vậy, Upstart nghĩ rằng công việc của tôi đã chết, và tôi không còn có thể khởi động lại nó với restart hoặc dừng nó với stop nếu tôi muốn.

Tôi đã chơi xung quanh với các tập tin cấu hình, cố gắng để thêm -D vào dòng Unicorn (như thế này: $APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production -D) daemonize Unicorn, và tôi đã thêm dòng expect daemon, nhưng điều đó không làm việc, hoặc. Tôi cũng đã thử số expect fork. Các kết hợp khác nhau của tất cả những thứ đó có thể gây ra startstop để treo, sau đó Upstart thực sự nhầm lẫn về trạng thái của công việc. Sau đó, tôi phải khởi động lại máy để sửa chữa nó.

Tôi nghĩ Upstart đang gặp sự cố khi phát hiện khi/nếu Unicorn đang tắt vì tôi đang sử dụng rbenv + ruby-local-exec shebang trong tập lệnh $APP_ROOT/bin/unicorn của tôi. Ở đây là:

#!/usr/bin/env ruby-local-exec 
# 
# This file was generated by Bundler. 
# 
# The application 'unicorn' is installed as part of a gem, and 
# this file is here to facilitate running it. 
# 

require 'pathname' 
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", 
    Pathname.new(__FILE__).realpath) 

require 'rubygems' 
require 'bundler/setup' 

load Gem.bin_path('unicorn', 'unicorn') 

Thêm vào đó, kịch bản ruby-local-exec trông như thế này:

#!/usr/bin/env bash 
# 
# `ruby-local-exec` is a drop-in replacement for the standard Ruby 
# shebang line: 
# 
# #!/usr/bin/env ruby-local-exec 
# 
# Use it for scripts inside a project with an `.rbenv-version` 
# file. When you run the scripts, they'll use the project-specified 
# Ruby version, regardless of what directory they're run from. Useful 
# for e.g. running project tasks in cron scripts without needing to 
# `cd` into the project first. 

set -e 
export RBENV_DIR="${1%/*}" 
exec ruby "[email protected]" 

Vì vậy, có một exec trong đó mà tôi đang lo lắng về. Nó khởi động một quá trình Ruby, nó sẽ làm cho Unicorn, có thể hoặc không thể tự daemon, mà tất cả xảy ra từ một quy trình sh ngay từ đầu ... điều này khiến tôi nghi ngờ khả năng Upstart theo dõi tất cả những điều vô nghĩa này.

Là những gì tôi đang cố gắng làm thậm chí có thể? Từ những gì tôi hiểu, đoạn quảng cáo expect trong Upstart chỉ có thể được thông báo (qua daemon hoặc fork) để mong đợi tối đa là hai nhánh.

Trả lời

15

công việc mới nổi của bạn cần phải được định cấu hình để mới nổi biết chính xác số lần dĩa của nó. Và nó chỉ có thể ngã ba một hoặc hai lần, không còn nữa.

Trong vùng đất liền có hai cuộc gọi hệ thống chính hỗ trợ các chương trình đang chạy: forkexec.

fork sao chép quy trình gọi nó. Một quá trình gọi fork và trả về kiểm soát trở lại hai quy trình. Mỗi quá trình phải xác định đó là (cha mẹ hoặc đứa trẻ) từ giá trị trả về bởi ngã ba (xem trang hướng dẫn để biết chi tiết).

exec chạy chương trình mới, thay thế quy trình được gọi là exec.

Khi bạn chỉ cần chạy lệnh trong trình bao, bên dưới nắp vỏ gọi fork để tạo quy trình mới với id riêng và quy trình mới (sau khi thiết lập) ngay lập tức gọi exec để bắt đầu lệnh bạn đã nhập . Đây là cách hầu hết các chương trình được chạy, cho dù bằng trình bao hay trình quản lý cửa sổ của bạn hay bất kỳ thứ gì. Xem hàm system trong C, cũng có các biến thể trong hầu hết các ngôn ngữ kịch bản.

Nếu bạn cho rằng nó không hiệu quả, có lẽ bạn đã đúng. Đó là cách nó đã được thực hiện trong unix kể từ ngày của yore, và rõ ràng không ai là trò chơi để thay đổi nó. Một trong những lý do là có rất nhiều thứ được không thay thế trên exec, bao gồm (đôi khi) các tệp mở và id người dùng và nhóm của quá trình.

Một lý do khác là rất nhiều nỗ lực đã được chi làm fork hiệu quả, và họ đã thực sự làm một công việc khá tốt của nó - trong unixes hiện đại (với sự giúp đỡ của CPU) fork thực bản sao rất ít của quá trình . Tôi đoán không ai muốn ném tất cả công việc đó đi.

Và, (tạm dừng để có hiệu lực) các quy trình pid.

Để chứng minh:

[email protected]:~$ echo $$ 
3652 
[email protected]:~$ bash 
[email protected]:~$ echo $$ 
6545 
[email protected]:~$ exec bash 
[email protected]:~$ echo $$ 
6545 
[email protected]:~$ exit 
exit 
[email protected]:~$ echo $$ 
3652 

Hầu hết các ngôn ngữ phổ biến có các biến thể của ngã ba và exec, bao gồm vỏ, C, perl, ruby ​​và python. Nhưng không phải java. Vì vậy, với tất cả những gì trong tâm trí, những gì bạn cần làm để làm cho công việc mới nổi của bạn là đảm bảo rằng nó dĩa cùng một số lần như mới nổi nghĩ rằng nó làm.

Dòng exec trong ruby-local-exec thực sự là một điều tốt, nó ngăn cản một ngã ba. Ngoài ra load không bắt đầu quá trình mới, nó chỉ tải mã vào trình thông dịch ruby ​​hiện có và chạy nó.

Tuy nhiên dĩa shell script của bạn trong dòng này:

$APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production # >> /tmp/upstart.log 2>&1 

để ngăn chặn điều này bạn chỉ có thể thay đổi nó để

exec $APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production # >> /tmp/upstart.log 2>&1 

Nếu bạn làm điều đó, AFAICT lân không nên ngã ba ở tất cả, và bạn sẽ không cần phải nói mới để mong đợi một cái nĩa.

+0

Tuyệt vời, cảm ơn vì điều đó. – codykrieger

+0

Cảm ơn bạn đã trả lời chi tiết! Nó chỉ giúp tôi thiết lập Thiên Chúa + Upstart trong tình huống giống hệt nhau. – dreikanter