Untuk melakukan pembersihan jika layanan gagal, Anda dapat menggunakan ExecStopPost=
, yang dijalankan apakah layanan berhasil atau tidak.
Dalam kode yang Anda jalankan di ExecStopPost=
, Anda dapat menggunakan salah satu dari $SERVICE_RESULT
, $EXIT_CODE
atau $EXIT_STATUS
untuk menentukan kondisi kegagalan dan bertindak sesuai dengan itu. Lihat dokumentasi pada variabel lingkungan tersebut untuk memeriksa mana yang sesuai untuk Anda.
Kemudian Anda dapat menggunakan Restart=on-failure
sehingga systemd mencoba me-restart unit Anda ketika gagal.
Menyatukan semuanya, seperti inilah tampilannya. Dengan asumsi bahwa run_program
akan keluar dengan status 2 setiap kali file rusak (semoga Anda dapat menyesuaikan ini dengan skenario kegagalan lain dari dokumentasi di atas), ini akan berfungsi:
[Service]
ExecStart=/bin/run_program
ExecStopPost=/bin/sh -c 'if [ "$$EXIT_STATUS" = 2 ]; then rm /file/to/delete; fi'
Restart=on-failure
(CATATAN :Tanda dolar ganda $$
adalah untuk menghindari ini ke systemd, sehingga shell melihat $EXIT_STATUS
dan mengakses variabel itu. Menggunakan satu tanda dolar juga akan berfungsi, tetapi kemudian systemd akan melakukan penggantian itu dan shell akan melihat [ "2" = 2 ]
, yang bisa dibilang juga berfungsi ... Bagaimanapun, Anda dapat melewati sebagian besar dari itu dengan memasukkan semua logika ini ke dalam skrip shell dan memanggilnya dengan jalur lengkapnya di ExecStopPost=
, itu mungkin lebih baik dan Anda juga dapat dengan mudah menambahkan lebih banyak perintah ke skrip, seperti mencatat tindakan yang diambil untuk memulihkan dari kondisi kesalahan.)
Mudah-mudahan ini akan memberi Anda petunjuk yang cukup untuk mengetahui cara mengonfigurasi ini dengan benar mengingat situasi khusus Anda!
CATATAN :Anda mungkin ingin menggunakan ExecStopPost=
bukannya OnFailure=
di sini (lihat jawaban saya yang lain), tetapi ini mencoba menjawab mengapa OnFailure=
Anda penyiapan tidak berfungsi.
Masalah dengan OnFailure=
tidak memulai unit mungkin karena berada di bagian yang salah, harus ada di [Unit]
bagian dan bukan [Service]
.
Anda dapat mencoba ini sebagai gantinya:
# software.service
[Unit]
Description=Software
OnFailure=software-fail.service
[Service]
ExecStart=/bin/run_program
Dan:
# software-fail.service
[Unit]
Description=Delete corrupt files
[Service]
ExecStart=/bin/rm /file/to/delete
ExecStop=/bin/systemctl --user start software.service
Saya dapat membuatnya berfungsi dengan penyiapan ini.
Tetapi perhatikan bahwa menggunakan OnFailure=
tidak ideal di sini, karena Anda tidak dapat benar-benar mengetahui mengapa program gagal, dan merantai awal lainnya di ExecStop=
dengan memanggil /bin/systemctl start
langsung cukup hacky ... Solusinya menggunakan ExecStopPost=
dan melihat status keluar pasti lebih unggul.
Jika Anda mendefinisikan OnFailure=
di dalam [Service]
, systemd (setidaknya versi 234 dari Fedora 27) mengeluh dengan:
software.service:6: Unknown lvalue 'OnFailure' in section 'Service'
Tidak yakin apakah Anda melihatnya di log Anda atau tidak... (Mungkin ini ditambahkan di systemd terbaru?) Itu seharusnya menjadi petunjuk tentang apa yang terjadi di sana.