Come recuperare indietro, piuttosto che arrendersi


24

Voglio che Upstart faccia due cose:

  1. smettere di provare a rigenerare un processo fallito così in fretta
  2. non mollare mai cercando di rigenerarsi

In un mondo ideale, upstart proverebbe a riavviare un processo morto dopo 1 secondo, quindi raddoppierà quel ritardo ad ogni tentativo, fino a raggiungere un'ora.

È possibile qualcosa del genere?


never give up trying to respawnrimane senza risposta. chiunque?
Vemv,

Risposte:


29

Il Cookbook Upstart raccomanda un ritardo post-stop ( http://upstart.ubuntu.com/cookbook/#delay-respawn-of-a-job ). Usa la respawnstanza senza argomenti e continuerà a provare per sempre:

respawn
post-stop exec sleep 5

(Ho preso questo da questa domanda di Ubuntu )

Per aggiungere la parte del ritardo esponenziale, proverei a lavorare con una variabile d'ambiente nello script post-stop, penso che qualcosa del tipo:

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

** MODIFICARE **

Per applicare il ritardo solo quando si respawn, evitando il ritardo su un arresto reale, utilizzare quanto segue, che controlla se l'obiettivo attuale è "stop" o meno:

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
Se si utilizza respawn senza argomenti, per impostazione predefinita è necessario riprovare fino a dieci volte in una finestra di cinque minuti.
Jamie Cockburn,

3
Il problema con questo per un sistema di produzione è che una volta raggiunto il massimo (anni '60) ci vorranno sempre 60 secondi anche se il sistema è tornato in buona salute. Forse potrebbe esserci un post-startripristino su 1.
José F. Romaniello,

2
@JamieCockburn L'intervallo predefinito non è 5 minuti, è 5 secondi .
Zitrax,

1
Questo ha funzionato quasi per me, ma il trucco set-env ha colpito "initctl: non è consentito modificare l'ambiente di lavoro PID 1". Invece ho dovuto ricorrere all'archiviazione del valore del sonno in / tmp / $ UPSTART_JOB e quindi al suo approvvigionamento di nuovo
Neil McGill

5

Come già accennato, usa respawnper innescare il respawn.

Tuttavia, la copertura Upstart Cookbook surespawn-limit dice che dovrai specificare respawn limit unlimitedper avere un comportamento di riprovare continuo.

Per impostazione predefinita, riproverà fino a quando il processo non si rigenererà più di 10 volte in 5 secondi.

Pertanto suggerirei:

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

4

Ho finito per mettere un startin un cronjob. Se il servizio è in esecuzione, non ha alcun effetto. Se non è in esecuzione, avvia il servizio.


3
Così stravagante ed elegante! <3
pkoch,

3

Ho migliorato la risposta di Roger. In genere si desidera eseguire il backoff quando si verifica un problema nel software sottostante che causa un arresto anomalo molto in un breve periodo di tempo, ma una volta ripristinato il sistema si desidera ripristinare il tempo di backoff. Nella versione di Roger il servizio dormirà sempre per 60 secondi, anche per crash singoli e isolati dopo 7 crash.

#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

Volete respawn limit <times> <period>- sebbene questo non fornisca il comportamento esponenziale che state cercando, probabilmente lo farebbe per la maggior parte dei casi d'uso. Potresti provare a usare valori molto grandi per timese periodapprossimare ciò che cerchi di raggiungere. Vedere l' uomo 5 init sezione 's su respawn limitper riferimento.


6
Il periodo è il periodo in cui vengono conteggiate le respawn , non un ritardo tra respawns.
fadedbee,

1
Il che presumo significherebbe che anche se avessi usato respawn limit 10 3600i 10 tentativi probabilmente verrebbero esauriti immediatamente - poiché di default non c'è ritardo.
Zitrax,

0

Altri hanno risposto alla domanda per le stanze limite di respawn e respawn, ma vorrei aggiungere la mia soluzione per lo script post-stop che controlla il ritardo tra il riavvio.

Il problema più grande con la soluzione proposta da Roger Dueck è che il ritardo provoca il blocco di "riavvia jobName" fino al completamento della sospensione.

La mia aggiunta verifica se è in corso un riavvio prima di determinare se dormire o meno.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.