Semalam terowong berfungsi, dan pagi ini unit mati dengan Failed at step EXEC spawning /usr/local/bin/vpnclient dalam jurnal. Kelayakan, laluan dan akaun tidak pernah masuk ke ayat itu. systemd menyelesaikan ExecStart kepada satu laluan, meminta kernel melaksanakannya, dan kernel menolak, selalunya kerana tiada apa-apa pada laluan itu atau fail itu tidak boleh laku. Anggap kerosakan ini sebagai masalah fail dan argv sehingga arahan yang dihuraikan membuktikan sebaliknya.

Mengapa EXEC gagal sebelum pengesahan bermula

systemd tidak menjalankan ExecStart melalui shell. Ia melakukan fork, membina vektor argumen daripada baris itu dan memanggil execve pada elemen pertama. Jika panggilan itu gagal, perkhidmatan tidak pernah sampai ke kod klien VPN itu sendiri, jadi penyuntingan profil atau pemeriksaan kelayakan tidak dapat membantu.

Kod status memisahkan keluarga ini daripada kerosakan biasa. Unit yang keluar dengan status=203/EXEC tidak pernah memulakan proses; unit yang bermula kemudian keluar dengan status=1 mungkin gagal pada pengesahan, DNS atau penghalaan. Baca kod sebelum membaca log klien, kerana dalam kes pertama log klien akan kosong.

Laluan dalam jurnal ialah laluan yang digunakan oleh systemd, bukan semestinya laluan yang anda sunting. Fail drop-in dan output penjana boleh mengatasi fail vendor, dan daemon-reload yang lapuk meninggalkan baris lama dalam memori. Sebab itu diagnostik pertama ialah bertanya kepada systemd apa yang dianggapnya arahan, bukannya membuka fail yang anda ingat telah diubah.

Tiga tempat laluan binari ditulis

Klien VPN yang dipasang daripada pakej pengedaran, skrip vendor dan tarball keluaran boleh mendarat dalam tiga awalan berbeza. Unit, peraturan keistimewaan dan pemasang masing-masing merekodkan satu daripada awalan itu, dan kegagalan muncul apabila dua daripada tiga tidak sepadan.

RecordCommon valueHow to read it
Unit or drop-in/usr/local/bin/vpnclientsystemctl cat vpnclient.service
Installed binary/usr/bin/vpnclientcommand -v vpnclient, then ls -l the result
Sudoers grant/opt/vpnclient/bin/vpnclientsudo grep -r vpnclient /etc/sudoers.d/

Ketidakseragaman konkrit kelihatan seperti ini: skrip vendor memasang ke /usr/local/bin, tarball diekstrak di bawah /opt, dan unit masih menamakan laluan /usr/bin lama daripada pakej sebelumnya. Hanya satu daripada fail itu wujud, dan jarang sekali ia fail dalam ExecStart.

Tentukan laluan mana yang kanonik sebelum mengubah mana-mana fail. Jika pakej pengedaran memiliki binari itu, laluan pakej ialah yang kanonik dan unit mesti mengikutinya. Jika skrip vendor yang memilikinya, peraturan yang sama terpakai pada awalan vendor. Menyalin binari antara awalan mencipta dua salinan yang berpisah pada peningkatan seterusnya.

Apabila arahan dalam tanda petik menjadi nama fail

Mod kegagalan kedua bersembunyi di sebalik baris jurnal yang sama. Seseorang menulis ini ke dalam unit dan menjangkakan klien akan bersambung semasa but:

ExecStart=/usr/bin/"vpnclient connect office"

systemd memecahkan nilai kepada perkataan, jadi perkataan pertama menjadi /usr/bin/vpnclient connect office dengan tanda petik dibuang sebagai sintaks pengelompokan. Kemudian kernel mencari fail yang namanya mengandungi ruang, dan fail itu tiada. Ralat itu sama seperti binari yang hilang walaupun binari itu dipasang.

Bentuk yang disokong ialah fail boleh laku sebenar diikuti argumen berasingan, contohnya ExecStart=/usr/bin/vpnclient connect office. Jika aliran kerja benar-benar memerlukan saluran paip atau rantaian, letakkan dalam skrip dan panggil skrip itu, kerana ExecStart tiada &&, tiada paip dan tiada pengembangan glob.

Betulkan unit, bukan sistem fail

Pembaikan yang menggoda ialah pautan simbolik daripada laluan yang dijangka ke binari sebenar. Ia berfungsi sehingga pakej dikemas kini dan pautan menunjuk kepada fail yang telah dibuang, atau sehingga label SELinux tidak lagi sepadan dengan sasaran. Lebih baik sunting unit melalui drop-in supaya fail vendor kekal utuh dan peningkatan kekal boleh dijangka.

Peraturan keistimewaan mesti sepadan dengan laluan yang sama dan subarahan yang sama. Entri sudoers untuk /usr/local/bin/vpnclient tidak membenarkan /usr/bin/vpnclient, dan entri yang membenarkan setiap argumen membolehkan mana-mana proses setempat mengkonfigurasi semula atau menghentikan terowong. Berikan dua kata kerja yang diperlukan unit dan jauhkan pembongkaran daripadanya jika menghentikan perkhidmatan sudah menutup antara muka.

Di sinilah perbandingan berbaloi: unit, pangkalan data pakej dan sudoers sepatutnya menamakan satu laluan. Apabila mereka berbuat demikian, ralat EXEC hilang tanpa but semula dan tanpa salinan binari di lokasi ketiga.

Buktikan arahan yang dihuraikan sebelum but semula

sudo systemctl daemon-reload
sudo systemctl cat vpnclient.service
systemctl show -p ExecStart vpnclient.service
systemd-analyze verify /etc/systemd/system/vpnclient.service
sudo systemctl restart vpnclient.service
systemctl status vpnclient.service --no-pager

systemctl show ialah output penentu kerana ia mencetak argv yang benar-benar dihuraikan oleh systemd, termasuk mana-mana drop-in. systemd-analyze verify menangkap laluan yang hilang atau tidak boleh laku sebelum anda memulakan semula, dan arahan status selepas permulaan semula memberitahu sama ada proses itu kini wujud.

Jika unit bermula kemudian gagal, anda telah meninggalkan keluarga EXEC dan memasuki pengendalian ralat klien itu sendiri. Periksa jurnal untuk mesej klien, bukan kegagalan execve yang lain. Simpan diff unit dan diff sudoers bersama dalam rekod perubahan supaya peningkatan seterusnya tidak mengembalikan semula laluan yang terbelah secara senyap.

Artikel berkaitan