Systemd Restart = selalu tidak tersanjung

54

Catatan: Saya menulis artikel di Medium yang menjelaskan cara membuat layanan, dan cara menghindari masalah khusus ini: Membuat layanan Linux dengan systemd .

Pertanyaan asli:


Saya menggunakan systemd untuk membuat skrip pekerja berfungsi setiap saat:

[Unit]
Description=My worker
After=mysqld.service

[Service]
Type=simple
Restart=always
ExecStart=/path/to/script

[Install]
WantedBy=multi-user.target

Meskipun restart berfungsi dengan baik jika skrip keluar secara normal setelah beberapa menit, saya perhatikan bahwa jika itu berulang kali gagal dieksekusi pada startup, systemdhanya akan menyerah mencoba untuk memulainya:

Jun 14 11:10:31 localhost systemd[1]: test.service: Main process exited, code=exited, status=1/FAILURE
Jun 14 11:10:31 localhost systemd[1]: test.service: Unit entered failed state.
Jun 14 11:10:31 localhost systemd[1]: test.service: Failed with result 'exit-code'.
Jun 14 11:10:31 localhost systemd[1]: test.service: Service hold-off time over, scheduling restart.
Jun 14 11:10:31 localhost systemd[1]: test.service: Start request repeated too quickly.
Jun 14 11:10:31 localhost systemd[1]: Failed to start My worker.
Jun 14 11:10:31 localhost systemd[1]: test.service: Unit entered failed state.
Jun 14 11:10:31 localhost systemd[1]: test.service: Failed with result 'start-limit'.

Demikian pula, jika skrip pekerja saya gagal beberapa kali dengan status keluar dari 255, systemdmenyerah mencoba untuk me-restart itu:

Jun 14 11:25:51 localhost systemd[1]: test.service: Failed with result 'exit-code'.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Service hold-off time over, scheduling restart.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Start request repeated too quickly.  
Jun 14 11:25:51 localhost systemd[1]: Failed to start My worker.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Unit entered failed state.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Failed with result 'start-limit'.

Apakah ada cara untuk memaksa systemduntuk selalu mencoba lagi setelah beberapa detik?

Benjamin
sumber

Jawaban:

53

Saya ingin sedikit memperluas jawaban Rahul.

SystemD mencoba memulai ulang beberapa kali ( StartLimitBurst) dan berhenti mencoba jika jumlah upaya tercapai di dalam StartLimitIntervalSec. Kedua opsi termasuk [unit]bagian.

Penundaan default antara eksekusi adalah 100ms ( RestartSec) yang menyebabkan batas laju tercapai sangat cepat.

SystemD tidak akan mencoba me-restart lagi secara otomatis untuk unit-unit dengan kebijakan Restart ditentukan :

Perhatikan bahwa unit yang dikonfigurasikan untuk Restart=dan yang mencapai batas awal tidak diusahakan untuk dimulai kembali; Namun, mereka mungkin masih direstart secara manual di titik kemudian, dari titik mana, logika restart diaktifkan kembali.

Jawaban Rahul membantu, karena penundaan yang lebih lama mencegah mencapai penghitung kesalahan dalam StartLimitIntervalSecwaktu. Jawaban yang benar adalah mengatur keduanya RestartSecdan StartLimitBurstnilai-nilai yang masuk akal.

MarSik
sumber
5
Sekarang saya (akhirnya) mengerti cara kerjanya, setelah beberapa trial-and-error, saya dapat melihat bahwa jawaban Anda adalah yang paling benar. Intinya bagi saya: atur StartLimitIntervalSec=0dan voila.
Benjamin
35

Ya ada. Anda dapat menentukan untuk mencoba lagi setelah xdetik di bawah [Service]bagian,

[Service]
Type=simple
Restart=always
RestartSec=3
ExecStart=/path/to/script

Setelah menyimpan file, Anda perlu memuat ulang konfigurasi daemon untuk memastikan systemdmengetahui file baru,

systemctl daemon-reload

kemudian restart layanan untuk mengaktifkan perubahan,

systemctl restart test

Seperti yang Anda minta, Melihat dokumentasi,

Restart=on-failure

Kedengarannya seperti rekomendasi yang layak.

Rahul
sumber
Tampaknya memang berhasil, terima kasih! Jadi, untuk memahami ini dengan lebih baik, tanpa RestartSecarahan, systemdupaya severals memulai kembali dengan sangat cepat, lalu memasuki kondisi kegagalan permanen; sesuatu yang tidak bisa terjadi ketika RestartSecditentukan?
Benjamin
Juga, saya perhatikan bahwa itu menunda restart "normal" pekerja saya (saya sengaja keluar pekerja dengan anggun setelah beberapa menit); adakah cara untuk hanya menunda restart yang gagal ?
Benjamin
@Benjamin, lihat pembaruan saya
Rahul
@Benjamin Anda dapat memeriksa di sini untuk parameter lainnya.
Rahul
3
Menilai oleh dokter , alwaysadalah superset dari on-failure, jadi itu tidak akan membantu!
Benjamin
5

systemd menyerah mencoba untuk me-restart itu

Tidak. Systemd menyerah untuk mencoba menghidupkannya kembali sebentar . Ini jelas ditunjukkan dalam log yang Anda berikan:

14 Jun 11:25:51 localhost systemd [1]: test.service: Gagal dengan hasil 'mulai-batas' .

Ini adalah pembatasan laju tendangan masuk.

Panjang sebentar ditentukan dalam unit layanan, menggunakan StartLimitIntervalSec=pengaturan. Jumlah awal yang diperlukan dalam interval itu untuk memicu mekanisme pembatasan laju ditentukan melalui StartLimitBurst=pengaturan. Jika tidak ada yang berbeda pada sistem Anda dari vanilla systemd, termasuk pengaturan default untuk kedua pengaturan ini, maka itu adalah 5 kali dalam 10 detik.

StartLimitIntervalSec=0menonaktifkan pembatasan tingkat, jadi systemd akan mencoba lagi selamanya daripada menyerah. Tetapi membuat layanan Anda tidak sering keluar, atau cukup menganggur antara keluar dan memulai ulang sehingga tidak melebihi ambang batas tingkat tarif, adalah pendekatan yang lebih baik.

Perhatikan bahwa pembatasan tarif tidak peduli bagaimana layanan Anda keluar. Ini memicu pada sejumlah upaya untuk memulai / memulai ulang, terlepas dari penyebabnya.

Bacaan lebih lanjut

JdeBP
sumber
5
Tampaknya menyerah secara permanen, meskipun: "Aktif: gagal (Hasil: mulai-batas) sejak Rab 2016-06-15 01:21:24 CEST; 12 jam yang lalu". Itu tetap dalam keadaan ini dan skrip tidak pernah dieksekusi lagi. Saya mencoba pengaturan secara manual StartLimitIntervalSec=10dan StartLimitIntervalSec=5, tidak berhasil.
Benjamin
5
Memang menyerah secara default. Lihat github.com/systemd/systemd/issues/2416 .
Adam Goode
2
Intinya: untuk berhenti mencegahnya menyerah secara permanen, atur StartLimitIntervalSec=0.
Benjamin