Cara make up pemula, bukan menyerah

24

Saya ingin pemula melakukan dua hal:

  1. berhentilah mencoba untuk memulai kembali proses yang gagal dengan sangat cepat
  2. jangan pernah menyerah mencoba untuk respawn

Dalam dunia yang ideal, pemula akan mencoba memulai kembali proses mati setelah 1s, lalu menggandakan penundaan itu pada setiap upaya, hingga mencapai satu jam.

Apakah hal seperti ini mungkin?

fadedbee
sumber
never give up trying to respawntetap tidak dijawab. siapa saja?
vemv

Jawaban:

29

Cookbook Upstart merekomendasikan penundaan post-stop ( http://upstart.ubuntu.com/cookbook/#delay-respawn-of-a-job ). Gunakan respawnbait tanpa argumen dan itu akan terus mencoba selamanya:

respawn
post-stop exec sleep 5

(Saya mendapatkan ini dari ini Tanyakan pertanyaan Ubuntu )

Untuk menambahkan bagian penundaan eksponensial, saya akan mencoba bekerja dengan variabel lingkungan di skrip pasca-berhenti, saya pikir sesuatu seperti:

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 **

Untuk menerapkan penundaan hanya saat respawn, menghindari keterlambatan pada perhentian nyata, gunakan yang berikut, yang memeriksa apakah sasaran saat ini "berhenti" atau tidak:

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
Roger Dueck
sumber
1
Jika Anda menggunakan respawn tanpa argumen, defaultnya akan mencoba lagi hingga sepuluh kali dalam jendela lima menit.
Jamie Cockburn
3
Masalah dengan ini untuk sistem produksi adalah bahwa setelah Anda mencapai maks (60-an) akan selalu mengambil 60secs bahkan jika sistem kembali sehat. Mungkin ada yang bisa post-startmengatur ulang ke 1.
José F. Romaniello
2
@ JamieCockburn Interval default bukan 5 menit, 5 detik .
Zitrax
1
Ini hampir berhasil bagi saya - tetapi trik set-env menekan "initctl: Tidak diizinkan untuk mengubah lingkungan kerja PID 1". Alih-alih, saya terpaksa menggunakan nilai sleep di / tmp / $ UPSTART_JOB dan kemudian mengambilnya kembali
Neil McGill
5

Seperti yang telah disebutkan, gunakan respawnuntuk memicu respawn.

Namun, cakupan Cookbook Upstart padarespawn-limit mengatakan bahwa Anda harus menentukan respawn limit unlimiteduntuk memiliki perilaku coba lagi yang berkelanjutan.

Secara default akan mencoba lagi selama proses tidak respawn lebih dari 10 kali dalam 5 detik.

Karena itu saya akan menyarankan:

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

Saya akhirnya memasukkan startcronjob. Jika layanan berjalan, itu tidak berpengaruh. Jika tidak berjalan, itu memulai layanan.

fadedbee
sumber
3
Begitu janky dan elegan! <3
pkoch
3

Saya telah melakukan perbaikan pada jawaban Roger. Biasanya Anda ingin mundur ketika ada masalah dalam perangkat lunak yang mendasarinya yang menyebabkannya banyak crash dalam waktu singkat, tetapi begitu sistem pulih Anda ingin mengatur ulang waktu mundur. Dalam versi Roger layanan akan tidur selama 60 detik selalu, bahkan untuk crash tunggal dan terisolasi setelah 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
José F. Romaniello
sumber
1

Anda ingin respawn limit <times> <period>- meskipun ini tidak akan memberikan perilaku eksponensial yang Anda cari, mungkin akan berlaku untuk sebagian besar kasus penggunaan. Anda dapat mencoba menggunakan nilai yang sangat besar untuk timesdan periodmemperkirakan apa yang ingin Anda capai. Lihat bagian man 5 init di respawn limituntuk referensi.

the-wabbit
sumber
6
Periode adalah periode di mana respawn dihitung , bukan penundaan antar respawn.
fadedbee
1
Yang saya asumsikan akan berarti bahwa bahkan jika Anda menggunakan respawn limit 10 360010 mencoba kemungkinan akan segera habis - karena secara default tidak ada penundaan.
Zitrax
0

Yang lain telah menjawab pertanyaan untuk bait standar respawn dan respawn limit, tetapi saya ingin menambahkan solusi saya sendiri untuk skrip post-stop yang mengontrol penundaan antara memulai kembali.

Masalah terbesar dengan solusi yang diusulkan oleh Roger Dueck adalah bahwa keterlambatan menyebabkan 'restart jobName' untuk menggantung sampai tidur selesai.

Penambahan saya memeriksa untuk melihat apakah ada restart yang sedang berlangsung sebelum menentukan apakah akan tidur atau tidak.

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
Whitham Reeve
sumber