Как сделать выскочку обратно, а не сдаваться

24

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

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

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

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

fadedbee
источник
never give up trying to respawnостается без ответа. кто угодно?
Vemv

Ответы:

29

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

respawn
post-stop exec sleep 5

(Я получил это из этого вопроса Ask Ubuntu )

Чтобы добавить экспоненциальную задержку, я бы попробовал поработать с переменной окружения в скрипте post-stop, я думаю, что-то вроде:

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
Если вы используете респаун без аргументов, по умолчанию он повторяется до десяти раз в пятиминутном окне.
Джейми Кокберн
3
Проблема с этим для производственной системы состоит в том, что, как только вы достигнете максимума (60 с), он всегда будет проходить через 60 сек, даже если система вернется к работоспособному состоянию. Может быть, можно было post-startбы сбросить его до 1.
Хосе Ф. Романиелло
2
@JamieCockburn Интервал по умолчанию не 5 минут, это 5 секунд .
Цитракс
1
Это почти сработало для меня - но трюк set-env ударил "initctl: Недопустимо изменять среду задания PID 1". Вместо этого мне пришлось прибегнуть к хранению значения сна в / tmp / $ UPSTART_JOB и затем вернуть его обратно
Нил МакГилл
5

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

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

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

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

respawn
respawn limit unlimited
post-stop <script to back-off or constant delay>
pingles
источник
4

Я закончил тем, что положил startв cronjob. Если служба работает, это не имеет никакого эффекта. Если он не запущен, он запускает службу.

fadedbee
источник
3
Так дерзко и так элегантно! <3
пкоч
3

Я улучшил ответ Роджера. Как правило, вы хотите выполнить откат, если в базовом программном обеспечении возникла проблема, из-за которой оно часто зависало за короткий промежуток времени, но после восстановления системы вы хотите сбросить время отката. В версии Roger служба будет работать в течение 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приблизить то, что вы пытаетесь достичь. Смотрите раздел man 5 initrespawn limit для справки.

заместитель Wabbit
источник
6
Период - это период подсчета респавнов , а не задержка между респаунами.
Fadedbee
1
Что, как я полагаю, будет означать, что даже если вы использовали respawn limit 10 360010 попыток, они, скорее всего, были бы использованы немедленно - поскольку по умолчанию задержка отсутствует.
Цитракс
0

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

Самая большая проблема с решением, предложенным Роджером Дьюком, заключается в том, что задержка приводит к зависанию «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
Витам Рив
источник