Systemd: Bagaimana cara memastikan layanan "oneshot" dicoba ulang jika gagal pertama kali?

18

Saya telah membaca manual layanan systemd beberapa kali, tetapi saya masih tidak dapat menemukan pola dasar systemd:

Saya ingin menjalankan proses startup sekali (seperti wadah buruh pelabuhan, atau memformat drive) saat boot, berhasil selesai. Tetapi jika saya menggunakan Type = oneshot untuk itu, maka saya tidak bisa menggunakan Restart = on-failure, dan jika gagal, maka tidak akan mencoba lagi pekerjaan itu. Apakah saya melewatkan sesuatu yang jelas di sini?

Saya juga mencoba mengatur Type = simple dengan Restart = on-failure, tetapi dalam banyak kasus ini saya memerlukan perilaku berikut (dari halaman manual) yang diberikan oleh layanan oneshot:

Perilaku oneshot mirip dengan yang sederhana; namun, diharapkan proses tersebut harus keluar sebelum systemd memulai unit tindak lanjut.

Pembaruan:

JKnight
sumber
Salah satu solusi yang saya gunakan adalah untuk menghilangkan Restartdan membungkus my_cmd seperti ini ExecStart=/bin/sh -c 'while ! my_cmd; do sleep 1; done':, bersama dengan beberapa TimeoutStartSecnilai yang masuk akal .
rozcietrzewiacz
Sudahkah Anda melihat FailureAction = ? Mungkin dapat mencapai hal yang sama Restart=dengan mengatur FailureAction=[self.unit](ganti [self.unit] dengan nama unit). Agak kasar, tapi setidaknya eksplisit dan cukup mudah untuk diikuti.
Centimane
@Centimane FailureActionmengambil nilai yang sama dengan StartLimitAction, dan semua kecuali nonememicu semacam shutdown.
jpkotta

Jawaban:

5

Salah satu solusi yang mungkin saya coba adalah

  [Unit]
    Description=Tags instance and EBS vols
    After=docker.service
    Requires=docker.service

    [Service]
    ExecStartPre=/usr/bin/docker run --rm -v /opt/tag.sh:/tag.sh -v /opt:/ack --entrypoint=/bin/sh alpine /tag.sh
    ExecStartPre=/usr/bin/sh -c '[[ -e /opt/TAG_SUCCESS ]]'
    ExecStart=/usr/bin/rm /opt/TAG_SUCCESS
    Restart=on-failure
    RestartSec=30

Di mana skrip tag.shakan touch /ack/TAG_SUCCESSdi akhir eksekusi. Saya percaya ini mendekati perilaku yang diinginkan karena ExecStartPreakan secara berurutan mengeksekusi, menunggu penyelesaian yang berhasil sebelum menelepon ExecStartdan unit hanya dianggap Startingsatu kali ExecStartdipanggil pada titik mana kami yakin kami telah menyelesaikan tugas startup.

Tapi ini masih terasa seperti retasan raksasa?

JKnight
sumber
Ini bekerja dengan baik untuk saya, kecuali bahwa saya juga harus mengatur RemainAfterExit=yesagar unit tetap "aktif" sehingga unit lain dapat bergantung padanya.
Guss