Назад | Перейти на главную страницу

Как заставить выскочку отступить, а не сдаться

Я хочу, чтобы Upstart делал две вещи:

  1. хватит пытаться так быстро возродить неудачный процесс
  2. никогда не сдавайся, пытаясь возродиться

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

Возможно ли что-то подобное?

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

respawn
post-stop exec sleep 5

(Я получил это от этот вопрос Ask 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

Как уже упоминалось, используйте respawn чтобы вызвать возрождение.

Однако Описание Upstart Cookbook на respawn-limit говорит, что вам нужно указать respawn limit unlimited чтобы иметь постоянное поведение повтора.

По умолчанию он будет повторять попытку до тех пор, пока процесс не возродится более 10 раз за 5 секунд.

Поэтому я бы предложил:

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

В итоге я поставил start в cronjob. Если служба запущена, это не действует. Если он не запущен, запускает службу.

Я улучшил ответ Роджера. Обычно вы хотите откатиться, когда в базовом программном обеспечении есть проблема, вызывающая частые сбои в течение короткого периода времени, но после восстановления системы вы хотите сбросить время отсрочки. В версии Роджера служба будет спать 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

Вы хотите respawn limit <times> <period> - хотя это не обеспечило бы ожидаемого экспоненциального поведения, оно, вероятно, подойдет для большинства случаев использования. Вы можете попробовать использовать очень большие значения для times и period чтобы приблизиться к тому, чего вы пытаетесь достичь. Увидеть человек 5 инициализациираздел о respawn limit для справки.

Другие ответили на вопрос о строфах ограничения возрождения и возрождения, но я хотел бы добавить свое собственное решение для сценария пост-остановки, который контролирует задержку между перезапуском.

Самая большая проблема с решением, предложенным Роджером Дуеком, заключается в том, что задержка приводит к зависанию «restart jobName» до завершения перехода в спящий режим.

Мое дополнение проверяет, идет ли перезагрузка, прежде чем определять, нужно ли спать.

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