2012-08-23 14 views
29

Tôi đang chạy nhiều trường hợp của một người lao động như mô tả trong câu trả lời này: Starting multiple upstart instances automaticallyKhởi động lại Upstart dụ xử lý

Câu hỏi: Tôi có thể khởi động lại tất cả các trường cùng một lúc?

Để bắt đầu công nhân của tôi, tôi có thể làm:

initctl khởi my-công nhân

Mà sau đó cho phép tôi làm:

nhân tình trạng initctl N = 1 công nhân (1) bắt đầu/chạy, xử lý 551

nhân viên trạng thái initctl N = 2 công nhân (2) bắt đầu/Chạy, quá trình 552

Có cách nào để làm một cái gì đó như thế này:

initctl restart my-công nhân

Tôi muốn để có thể khởi động lại tất cả các trường mà không cần phải để biết có bao nhiêu người đang chạy.

Đây là của tôi my-workers.conf

start on stopped cloud-init 
stop on shutdown 

env NUM_WORKERS=4 

script 
    for i in `seq 1 $NUM_WORKERS` 
    do 
     start worker N=$i 
    done 
end script 

Và worker.conf

stop on shutdown 

chdir /path/to/current 

respawn 

instance $N 

script 
    exec su -c "/home/worker/.rvm/bin/rvm-shell -c 'bundle exec rake work 2>&1 >> /var/log/worker-$N.log'" worker 
end script 

Trả lời

35

Trong worker.conf bạn chỉ cần thay đổi dòng này:

stop on shutdown 

Để:

stop on stopping my-workers 

Và thay đổi my-workers.conf sử dụng pre-start thay vì script:

pre-start script 
    for i in `seq 1 $NUM_WORKERS` 
    do 
    start worker N=$i 
    done 
end script 

Bây giờ my-workers sẽ giữ trạng thái: kể từ khi công trình xảy ra trong pre-start, quá trình chính my-workers sẽ không tồn tại và như vậy sẽ không thoát. stop on stopping my-workers khiến người lao động dừng lại bất cứ khi nào my-workers bị dừng. Sau đó, tất nhiên khi nó bắt đầu lên một lần nữa nó sẽ bắt đầu công nhân một lần nữa.

(FYI, stop on shutdown không có gì, vì shutdown không phải là sự kiện hệ thống.man upstart-events cho tất cả các sự kiện được xác định), do đó bạn cũng nên thay đổi my-người lao động stop on runlevel [06]

+4

đưa tôi một lúc để hiểu ý bạn, nhưng một khi tôi nhận được ... * tâm thổi * – Evgeny

+0

@Evgeny cùng ở đây, haha. Nếu như tôi, và có thể là Evgeny, bạn chỉ cần dành 5 phút để hiểu những gì đang diễn ra ở đây: về cơ bản my-workers.conf sinh ra nhiều kịch bản và lối thoát mới, nhưng mỗi worker.conf giờ đây có dòng 'dừng việc dừng công nhân của tôi ', vì vậy khi bạn cố gắng ngăn chặn quá trình công nhân của tôi đã ngừng hoạt động, công nhân vẫn sẽ lắng nghe và chết. Vì vậy, "khởi động lại" công nhân của tôi, mặc dù nó đã không thực sự chạy trước, có tác dụng giết chết các công nhân (dừng lại) và chạy script khởi động lại (bắt đầu) một lần nữa, sinh ra chúng một lần nữa. – Mahn

+1

Nó hoạt động nhưng nó là khá hackish. 'service my-workers start' sẽ treo, trên thực tế. Tài liệu Upstart nêu rõ 'Tất cả các tệp công việc phải có một tập lệnh exec hoặc script stanza.'' trước khi bắt đầu và kịch bản lệnh dừng - Chúng không được mong đợi để bắt đầu quá trình, trên thực tế, chúng không thể.'. Có lẽ tốt hơn là tạo một công việc khác để dừng hoặc khởi động lại công nhân. –

7

Tôi đã thử nó với ví dụ từ trên cao và SpamapS trả lời, tôi nhận được:

init: my-workers pre-start process (22955) terminated with status 127 

Trong /var/log/upstart/my-workers.log tôi thấy vấn đề:

/proc/self/fd/9: 6: /proc/self/fd/9: end: not found 

các end của cho vòng lặp trong my-workers.conf dường như là cú pháp sai. tôi thay

script 
    for i in `seq 1 $NUM_WORKERS` 
    do 
     start worker N=$i 
    done 
    end 
end script 

với

script 
    for i in `seq 1 $NUM_WORKERS` 
    do 
    start worker N=$i 
    done 
end script 

và nó làm việc!

+1

Tuyệt vời, đã làm việc cho tôi! –

1

Hãy xem xét thêm đến worker.conf một sự kiện khác:

stop on shutdown or workers-stop 

Sau đó, bạn có thể gọi từ dòng lệnh

sudo initctl emit workers-stop 

Bạn có thể thêm sự kiện tương tự để bắt đầu công nhân. Để đạt được khởi động lại tất cả các công nhân tạo ra một nhiệm vụ mà sẽ phát ra công nhân dừng lại và sau đó các sự kiện bắt đầu công nhân.

0

Về cơ bản, bạn cần có quy trình thực hiện nhiều lệnh stopstart cho tất cả các kết hợp N=1, N=2 của bạn.

Cách đơn giản để thực hiện việc này là một vài vòng tròn for vòng bên trong một đoạn quảng cáo exec script. Tuy nhiên, nếu các quá trình mất một thời gian để dừng lại (ví dụ vì chúng đang làm việc trên một cái gì đó và chúng đang chấp nhận SIGTERM sau khi đã xử lý công việc hiện tại của chúng), điều này không hiệu quả vì bạn phải chờ dừng lại trước khi gửi tín hiệu đến cái tiếp theo .

Vì vậy, tôi đã xây dựng một kịch bản Upstart mà dừng lại chúng song song ở https://github.com/elifesciences/builder-base-formula/blob/master/elife/config/etc-init-multiple-processes-parallel.conf

Các kịch bản được biên soạn bởi Salt sử dụng như là đầu vào bản đồ về tên quá trình để có bao nhiêu là ở đó. Đây là kết quả mẫu:

description "(Re)starts all instances, in parallel" 
# http://upstart.ubuntu.com/cookbook/#start-on 
start on (local-filesystems and net-device-up IFACE!=lo) 
task 
script 
    timeout=300 
    echo "--------" 

    echo "Current status of 5 elife-bot-worker processes" 
    echo "Now is" $(date -Iseconds) 
    for i in `seq 1 5` 
    do 
     status elife-bot-worker ID=$i || true 
    done 
    echo "Stopping asynchronously 5 elife-bot-worker processes" 
    echo "Now is" $(date -Iseconds) 
    for i in `seq 1 5` 
    do 
     (stop elife-bot-worker ID=$i &) || true 
    done 

    for i in `seq 1 5` 
    do 
     echo "Waiting for elife-bot-worker $i to stop" 
     echo "Now is" $(date -Iseconds) 
     counter=0 
     while true 
     do 
      if [ "$counter" -gt "$timeout" ] 
      then 
       echo "It shouldn't take more than $timeout seconds to kill all the elife-bot-worker processes" 
       exit 1 
      fi 
      status elife-bot-worker ID=$i 2>&1 | grep "Unknown instance" && break 
      sleep 1 
      counter=$((counter + 1)) 
     done 
    done 
    echo "Stopped all elife-bot-worker processes" 

    echo "Starting 5 elife-bot-worker processes" 
    for i in `seq 1 5` 
    do 
     start elife-bot-worker ID=$i 
    done 
    echo "Started 5 elife-bot-worker processes" 

end script