Як змусити відштовхуватися, а не здаватися


24

Я хочу, щоб Upstart зробив дві речі:

  1. перестаньте так швидко відновлювати невдалий процес
  2. ніколи не відмовляйтеся від спроби відродитись

В ідеальному світі upstart намагатиметься перезапустити мертвий процес через 1 с, а потім подвоїти цю затримку на кожну спробу, поки не досяг години.

Чи можливо щось подібне?


never give up trying to respawnзалишається без відповіді. хтось?
vemv

Відповіді:


29

Початкова книга Upstart рекомендує затримку після зупинки ( http://upstart.ubuntu.com/cookbook/#delay-respawn-of-a-job ). Використовуйте respawnстрофу без аргументів, і вона продовжить намагатися назавжди:

respawn
post-stop exec sleep 5

(Я отримав це з цього питання Задати Ubuntu )

Щоб додати частину експоненціальної затримки, я б спробував працювати зі змінною середовища в сценарії після зупинки, я думаю, що на кшталт:

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

** редагувати **

Щоб застосувати затримку лише при повторному закладанні, уникаючи затримки на реальній зупинці, використовуйте наступне, яке перевіряє, чи є поточна мета "зупинка" чи ні:

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
Якщо ви користуєтесь respawn без аргументів, за замовчуванням його потрібно повторити до десяти разів у п'ятихвилинному вікні.
Джеймі Кокберн

3
Проблема цього для виробничої системи полягає в тому, що як тільки ви досягнете максимуму (60-х), він завжди займе 60 секунд, навіть якщо система повернеться до здорового. Можливо, може бути post-startскинути його до 1.
Хосе Ф. Романьєлло

2
@JamieCockburn Інтервал за замовчуванням не 5 хвилин, це 5 секунд .
Zitrax

1
Це майже не спрацювало для мене - але фокус set-env потрапив у "initctl: Не дозволяється змінювати завдання PID 1". Натомість мені довелося вдатися до збереження значення сну в / tmp / $ UPSTART_JOB, а потім повернути його назад
Ніл Макгілл

5

Як уже згадувалося, використовуйте respawnдля запуску відновлення.

Однак, висвітленняrespawn-limit програми Upstart Cookbook увімкнено, що вам потрібно вказати, respawn limit unlimitedщоб мати постійну поведінку.

За замовчуванням вона буде повторена, доки процес не відновлюється більше 10 разів за 5 секунд.

Тому я б запропонував:

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

4

Я в кінцевому підсумку ставив startу кронштейн. Якщо послуга запущена, це не має ефекту. Якщо він не працює, він запускає службу.


3
Так прискіпливо і так елегантно! <3
pkoch

3

Я зробив поліпшення відповіді Роджера. Як правило, ви хочете створити помилку, коли виникає проблема в базовому програмному забезпеченні, що призводить до краху роботи за короткий проміжок часу, але після відновлення системи ви хочете скинути час відновлення. У версії Роджера сервіс завжди буде спати 60 секунд, навіть для одиночних та ізольованих аварій після 7 аварій.

#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

Ви хочете respawn limit <times> <period>- хоча це не забезпечить експоненціальну поведінку, яку ви шукаєте, це, мабуть, зробить для більшості випадків використання. Ви можете спробувати використовувати дуже великі значення для timesта periodнаблизити те, що ви намагаєтеся досягти. Дивіться на людину 5 INIT розділ «з на respawn limitдля довідки.


6
Період - це період, за який підраховуються репауни , а не затримка між респаунами.
fadedbee

1
Я вважаю, що це означає, що навіть якщо ви використали respawn limit 10 360010 спроб, швидше за все, вони будуть використані негайно - оскільки за замовчуванням затримки немає.
Zitrax

0

Інші відповіли на питання щодо відновлення строку відновлення та відновлення, але я хотів би додати власне рішення для сценарію після зупинки, який контролює затримку між перезавантаженням.

Найбільша проблема рішення, запропонованого Роджером Дуеком, полягає в тому, що затримка викликає зависання функції «перезапуск робочого імені» до завершення сну.

Моє доповнення перевіряє, чи не відбувається перезавантаження, перш ніж визначити, спати чи ні.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.