Làm thế nào để bắt đầu trở lại, thay vì từ bỏ


24

Tôi muốn Upstart làm hai việc:

  1. ngừng cố gắng để hồi sinh một quá trình thất bại quá nhanh
  2. không bao giờ từ bỏ cố gắng để hồi sinh

Trong một thế giới lý tưởng, những người mới bắt đầu sẽ cố gắng khởi động lại một quá trình chết sau 1 giây, sau đó tăng gấp đôi độ trễ đó cho mỗi lần thử, cho đến khi đạt được một giờ.

Có phải bất cư thứ gì như thế này đều được?


never give up trying to respawnvẫn chưa được trả lời. bất kỳ ai?
vemv

Câu trả lời:


29

Upstart Cookbook khuyên bạn nên trì hoãn sau dừng ( http://upstart.ubfox.com/cookbook/#delay-respawn-of-a-job ). Sử dụng khổ respawnthơ mà không cần tranh luận và nó sẽ tiếp tục cố gắng mãi mãi:

respawn
post-stop exec sleep 5

(Tôi đã nhận được điều này từ câu hỏi Hỏi Ubuntu này )

Để thêm phần trì hoãn theo cấp số nhân, tôi sẽ thử làm việc với một biến môi trường trong tập lệnh dừng sau, tôi nghĩ một cái gì đó như:

env SLEEP_TIME=1
post-stop script
    sleep $SLEEP_TIME
    NEW_SLEEP_TIME=`expr 2 \* $SLEEP_TIME`
    if [ $NEW_SLEEP_TIME -ge 60 ]; then
        NEW_SLEEP_TIME=60
    fi
    initctl set-env SLEEP_TIME=$NEW_SLEEP_TIME
end script

** CHỈNH SỬA **

Để chỉ áp dụng độ trễ khi hồi sinh, tránh độ trễ khi dừng thực sự, hãy sử dụng cách sau, để kiểm tra xem mục tiêu hiện tại có "dừng" hay không:

env SLEEP_TIME=1
post-stop script
    goal=`initctl status $UPSTART_JOB | awk '{print $2}' | cut -d '/' -f 1`
    if [ $goal != "stop" ]; then
        sleep $SLEEP_TIME
        NEW_SLEEP_TIME=`expr 2 \* $SLEEP_TIME`
        if [ $NEW_SLEEP_TIME -ge 60 ]; then
            NEW_SLEEP_TIME=60
        fi
        initctl set-env SLEEP_TIME=$NEW_SLEEP_TIME
    fi
end script

1
Nếu bạn sử dụng hồi sinh mà không có đối số, mặc định nó sẽ thử lại tới mười lần trong một cửa sổ năm phút.
Jamie Cockburn

3
Vấn đề với điều này đối với một hệ thống sản xuất là một khi bạn đạt đến mức tối đa (60 giây), nó sẽ luôn mất 60 giây ngay cả khi hệ thống trở lại khỏe mạnh. Có lẽ có thể post-startđặt lại nó thành 1.
José F. Romaniello

2
@JamieCockburn Khoảng thời gian mặc định không phải là 5 phút, là 5 giây .
Zitrax

1
Điều này gần như đã làm việc với tôi - nhưng thủ thuật set-env đã nhấn "initctl: Không được phép sửa đổi môi trường công việc PID 1". Thay vào đó, tôi đã phải dùng đến việc lưu trữ giá trị giấc ngủ trong / tmp / $ UPSTART_JOB và sau đó tìm nguồn cung ứng lại
Neil McGill

5

Như đã đề cập, sử dụng respawnđể kích hoạt sự hồi sinh.

Tuy nhiên, phạm vi bảo hiểmrespawn-limit của Upstart Cookbook nói rằng bạn sẽ cần chỉ định respawn limit unlimitedđể có hành vi thử lại liên tục.

Theo mặc định, nó sẽ thử lại miễn là quá trình không hồi sinh hơn 10 lần trong 5 giây.

Do đó tôi sẽ đề nghị:

respawn
respawn limit unlimited
post-stop <script to back-off or constant delay>

4

Tôi cuối cùng đã đặt một starttrong một cronjob. Nếu dịch vụ đang chạy, nó không có hiệu lực. Nếu nó không chạy, nó sẽ khởi động dịch vụ.


3
Thật vui và thật tao nhã! <3
pkoch

3

Tôi đã thực hiện một cải tiến để trả lời Roger. Thông thường, bạn muốn sao lưu khi có sự cố trong phần mềm cơ bản khiến phần mềm bị sập rất nhiều trong một khoảng thời gian ngắn nhưng một khi hệ thống đã khôi phục, bạn muốn đặt lại thời gian chờ. Trong phiên bản của Rogers, dịch vụ sẽ luôn ngủ trong 60 giây, ngay cả đối với các sự cố đơn lẻ và bị cô lập sau 7 sự cố.

#The initial delay.
env INITIAL_SLEEP_TIME=1

#The current delay.
env CURRENT_SLEEP_TIME=1

#The maximum delay
env MAX_SLEEP_TIME=60

#The unix timestamp of the last crash.
env LAST_CRASH=0

#The number of seconds without any crash 
#to consider the service healthy and reset the backoff.
env HEALTHY_TRESHOLD=180

post-stop script
  exec >> /var/log/auth0.log 2>&1
  echo "`date`: stopped $UPSTART_JOB"
  goal=`initctl status $UPSTART_JOB | awk '{print $2}' | cut -d '/' -f 1`
  if [ $goal != "stop" ]; then
    CRASH_TIMESTAMP=$(date +%s)

    if [ $LAST_CRASH -ne 0 ]; then
      SECS_SINCE_LAST_CRASH=`expr $CRASH_TIMESTAMP - $LAST_CRASH`
      if [ $SECS_SINCE_LAST_CRASH -ge $HEALTHY_TRESHOLD ]; then
        echo "resetting backoff"
        CURRENT_SLEEP_TIME=$INITIAL_SLEEP_TIME
      fi
    fi

    echo "backoff for $CURRENT_SLEEP_TIME"
    sleep $CURRENT_SLEEP_TIME

    NEW_SLEEP_TIME=`expr 2 \* $CURRENT_SLEEP_TIME`
    if [ $NEW_SLEEP_TIME -ge $MAX_SLEEP_TIME ]; then
      NEW_SLEEP_TIME=$MAX_SLEEP_TIME
    fi

    initctl set-env CURRENT_SLEEP_TIME=$NEW_SLEEP_TIME
    initctl set-env LAST_CRASH=$CRASH_TIMESTAMP
  fi
end script

1

Bạn muốn respawn limit <times> <period>- mặc dù điều này sẽ không cung cấp hành vi theo cấp số nhân mà bạn đang tìm kiếm, nhưng nó có thể sẽ làm được cho hầu hết các trường hợp sử dụng. Bạn có thể thử sử dụng các giá trị rất lớn cho timesperiodđể tính gần đúng những gì bạn cố gắng đạt được. Xem man 5 init phần 's trên respawn limitđể tham khảo.


6
Khoảng thời gian là khoảng thời gian mà các lần hồi sinh được tính , không phải là sự chậm trễ giữa các lần hồi sinh.
fadedbee

1
Mà tôi cho rằng sẽ có nghĩa là ngay cả khi bạn đã sử dụng respawn limit 10 360010 lần thử có thể sẽ được sử dụng ngay lập tức - vì theo mặc định, không có độ trễ.
Zitrax

0

Những người khác đã trả lời câu hỏi cho các khổ thơ giới hạn và hồi sinh, nhưng tôi muốn thêm giải pháp của riêng mình cho tập lệnh dừng sau kiểm soát độ trễ giữa quá trình khởi động lại.

Vấn đề lớn nhất với giải pháp được đề xuất bởi Roger Dueck là sự chậm trễ khiến 'khởi động lại tên công việc' bị treo cho đến khi giấc ngủ được hoàn thành.

Bổ sung của tôi kiểm tra xem có tiến hành khởi động lại trước khi xác định có ngủ hay không.

respawn
respawn limit unlimited

post-stop script
    goal=`initctl status $UPSTART_JOB | awk '{print $2}' | cut -d '/' -f 1`
    if [[ $goal != "stop" ]]; then
            if ! ps aux | grep [r]estart | grep $UPSTART_JOB; then
                    sleep 60
            fi
    fi
end script
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.