Wie man Emporkömmlinge davon abhält, anstatt aufzugeben


24

Ich möchte, dass Upstart zwei Dinge tut:

  1. Hören Sie auf, so schnell zu versuchen, einen fehlgeschlagenen Prozess erneut zu starten
  2. Gib niemals auf, zu versuchen, wieder zu erscheinen

In einer idealen Welt würde Upstart versuchen, einen toten Prozess nach einer Sekunde neu zu starten und diese Verzögerung bei jedem Versuch zu verdoppeln, bis eine Stunde erreicht ist.

Ist so etwas möglich?


never give up trying to respawnbleibt unbeantwortet. jemand?
vemv

Antworten:


29

Das Upstart-Kochbuch empfiehlt eine Verzögerung nach dem Stopp ( http://upstart.ubuntu.com/cookbook/#delay-respawn-of-a-job ). Verwenden Sie die respawnZeilengruppe ohne Argumente und versuchen Sie es für immer:

respawn
post-stop exec sleep 5

(Ich habe dies von dieser Frage an Ubuntu bekommen. )

Um den exponentiellen Verzögerungsteil hinzuzufügen, würde ich versuchen, mit einer Umgebungsvariablen im Post-Stop-Skript zu arbeiten.

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

** EDIT **

Um die Verzögerung nur beim erneuten Auftauchen anzuwenden und die Verzögerung bei einem echten Stopp zu vermeiden, verwenden Sie Folgendes, um zu überprüfen, ob das aktuelle Ziel "Stopp" ist oder nicht:

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
Wenn Sie Respawn ohne Argumente verwenden, wird es standardmäßig bis zu zehn Mal in einem Fünf-Minuten-Fenster wiederholt.
Jamie Cockburn

3
Das Problem bei einem Produktionssystem besteht darin, dass bei Erreichen des Maximalwerts (60s) immer 60s benötigt werden, auch wenn das System wieder funktionsfähig ist. Vielleicht könnte es sein post-start, es auf 1 zurückzusetzen.
José F. Romaniello

2
@JamieCockburn Das Standardintervall beträgt nicht 5 Minuten, sondern 5 Sekunden .
Zitrax

1
Das hat bei mir fast geklappt - aber der set-env-Trick hat "initctl: PID 1-Jobumgebung darf nicht geändert werden". Stattdessen musste ich den Sleep-Wert in / tmp / $ UPSTART_JOB speichern und ihn dann wieder einlesen
Neil McGill,

5

Verwenden Sie respawn, wie bereits erwähnt, um den Respawn auszulösen.

In der Beschreibungrespawn-limit des Upstart-Kochbuchs wird jedoch angegeben , dass Sie angeben müssen, um respawn limit unlimitedein kontinuierliches Wiederholungsverhalten zu erzielen.

Standardmäßig wird der Vorgang wiederholt, solange der Vorgang nicht mehr als 10 Mal in 5 Sekunden erneut ausgeführt wird.

Ich würde daher vorschlagen:

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

4

startAm Ende habe ich einen Cronjob gemacht. Wenn der Dienst ausgeführt wird, hat er keine Auswirkungen. Wenn es nicht ausgeführt wird, wird der Dienst gestartet.


3
So ruckelig und so elegant! <3
pkoch

3

Ich habe eine Verbesserung an der Antwort von Roger vorgenommen. In der Regel möchten Sie einen Backoff ausführen, wenn ein Problem in der zugrunde liegenden Software auftritt, das in kurzer Zeit zu einem häufigen Absturz führt. Nach Wiederherstellung des Systems möchten Sie jedoch den Backoff zurücksetzen. In der Roger-Version wird der Dienst immer 60 Sekunden lang inaktiv sein, auch bei einzelnen und isolierten Abstürzen nach 7 Abstürzen.

#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

Sie möchten respawn limit <times> <period>- obwohl dies nicht das exponentielle Verhalten liefern würde, das Sie suchen, würde es wahrscheinlich für die meisten Anwendungsfälle reichen. Sie können versuchen, sehr große Werte für das zu erreichen, was Sie erreichen möchten, timesund perioddiese näherungsweise zu bestimmen. Weitere Informationen finden Sie im Abschnitt zu man 5 initrespawn limit .


6
Der Zeitraum ist der Zeitraum, in dem die Respawns gezählt werden , keine Verzögerung zwischen den Respawns.
Fadedbee

1
Was ich vermute, würde bedeuten, dass selbst wenn Sie respawn limit 10 3600die 10 Versuche verwendet hätten, diese wahrscheinlich sofort aufgebraucht wären - da es standardmäßig keine Verzögerung gibt.
Zitrax

0

Andere haben die Frage nach den Zeilengruppen "Respawn" und "Respawn-Limit" beantwortet, aber ich möchte meine eigene Lösung für das Post-Stop-Skript hinzufügen, das die Verzögerung zwischen dem Neustart steuert.

Das größte Problem bei der von Roger Dueck vorgeschlagenen Lösung besteht darin, dass 'restart jobName' aufgrund der Verzögerung hängen bleibt, bis der Ruhezustand abgeschlossen ist.

Mein Zusatz überprüft, ob ein Neustart durchgeführt wird, bevor festgestellt wird, ob der Schlafmodus aktiviert ist oder nicht.

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.