Jak zrezygnować z upstartu, zamiast się poddawać


24

Chcę, aby Upstart zrobił dwie rzeczy:

  1. przestań tak szybko odradzać nieudany proces
  2. nigdy się nie poddawaj, próbując się odrodzić

W idealnym świecie upstart próbowałby ponownie uruchomić martwy proces po 1 s, a następnie podwoić to opóźnienie przy każdej próbie, aż osiągnie godzinę.

Czy coś takiego jest możliwe?


never give up trying to respawnpozostaje bez odpowiedzi. ktoś?
vemv

Odpowiedzi:


29

Upstart Cookbook zaleca opóźnienie po zatrzymaniu ( http://upstart.ubuntu.com/cookbook/#delay-respawn-of-a-job ). Skorzystaj ze respawnzwrotki bez argumentów, a ona będzie próbować na zawsze:

respawn
post-stop exec sleep 5

(Mam to z tego pytania Zadaj Ubuntu )

Aby dodać część wykładniczą opóźnienia, spróbuję pracować ze zmienną środowiskową w skrypcie post-stop, myślę coś takiego:

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

** EDYTOWAĆ **

Aby zastosować opóźnienie tylko podczas odradzania, unikając opóźnienia przy rzeczywistym zatrzymaniu, skorzystaj z następujących poleceń, które sprawdzają, czy bieżącym celem jest „zatrzymanie”, czy nie:

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
Jeśli użyjesz odrodzenia bez argumentów, domyślnie będzie ono próbowało do dziesięciu razy w pięciominutowym oknie.
Jamie Cockburn,

3
Problem w tym przypadku w przypadku systemu produkcyjnego polega na tym, że gdy osiągniesz maksimum (60s), zawsze zajmie to 60 sekund, nawet jeśli system powróci do zdrowia. Może być post-startmoże zresetować go do 1.
José F. Romaniello

2
@JamieCockburn Domyślny odstęp nie wynosi 5 minut, to 5 sekund .
Zitrax,

1
To prawie dla mnie zadziałało - ale sztuczka set-env uderzyła „initctl: Niedopuszczalne jest modyfikowanie środowiska pracy PID 1”. Zamiast tego musiałem skorzystać z przechowywania wartości snu w / tmp / $ UPSTART_JOB, a następnie pozyskiwania jej z powrotem
Neil McGill

5

Jak już wspomniano, użyj, respawnaby uruchomić odrodzenie.

Jednak informacje na temat książki kucharskiej Upstartrespawn-limit mówią o tym, że musisz określić, respawn limit unlimitedaby zachować ciągłe ponawianie prób.

Domyślnie ponawia próbę, dopóki proces nie odrodzi się więcej niż 10 razy w ciągu 5 sekund.

Proponuję zatem:

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

4

Skończyło się startna tym, że robiłem cronjob. Jeśli usługa jest uruchomiona, nie ma to wpływu. Jeśli nie jest uruchomiony, uruchamia usługę.


3
Taki szalony i taki elegancki! <3
pkoch 26.04.16

3

Poprawiłem odpowiedź Rogera. Zazwyczaj chcesz wycofać się, gdy występuje problem w oprogramowaniu bazowym powodującym jego awarię w krótkim czasie, ale po odzyskaniu systemu chcesz zresetować czas wycofania. W wersji Rogera usługa będzie spała zawsze przez 60 sekund, nawet w przypadku pojedynczych i pojedynczych awarii po 7 awarii.

#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

Chcesz respawn limit <times> <period>- chociaż nie zapewniłoby to wykładniczego zachowania, którego szukasz, prawdopodobnie zrobiłoby to w większości przypadków użycia. Możesz spróbować użyć bardzo dużych wartości timesi perioddo przybliżenia tego, co próbujesz osiągnąć. Zobacz sekcję man 5 init w respawn limitcelu odniesienia.


6
Okres to okres, w którym liczone są odrodzenia , a nie opóźnienie między odradzaniami.
fadedbee

1
Zakładam, że oznaczałoby to, że nawet jeśli użyjesz respawn limit 10 360010 prób, prawdopodobnie zostaną zużyte natychmiast - ponieważ domyślnie nie ma opóźnienia.
Zitrax,

0

Inni odpowiedzieli na pytania dotyczące zwrotek i limitów odradzania, ale chciałbym dodać własne rozwiązanie dla skryptu post-stop, który kontroluje opóźnienie między ponownym uruchomieniem.

Największy problem z rozwiązaniem zaproponowanym przez Rogera Duecka polega na tym, że opóźnienie powoduje zawieszenie się „restart jobName” aż do zakończenia snu.

Moje dodanie sprawdza, czy trwa restart, zanim zdecyduję, czy spać.

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.