Layanan VPN gagal di EXEC: bandingkan unit, biner, dan sudoers
Gagal pada langkah EXEC berarti systemd tidak dapat menjalankan biner. Bandingkan jalur unit, jalur terpasang, dan izin sudoers sebelum mengubah apa pun.
Kemarin terowongan berfungsi, dan pagi ini unit mati dengan Failed at step EXEC spawning /usr/local/bin/vpnclient di jurnal. Kredensial, rute, dan akun tidak pernah masuk ke kalimat itu. systemd menyelesaikan ExecStart menjadi sebuah jalur, meminta kernel menjalankannya, dan kernel menolak, paling sering karena tidak ada apa pun di jalur itu atau berkasnya tidak dapat dieksekusi. Perlakukan kesalahan ini sebagai masalah berkas dan argv sampai perintah yang diurai membuktikan sebaliknya.
Mengapa EXEC gagal sebelum autentikasi dimulai
systemd tidak menjalankan ExecStart melalui shell. Ia melakukan fork, membangun vektor argumen dari baris itu, dan memanggil execve pada elemen pertama. Jika panggilan itu gagal, layanan tidak pernah mencapai kode klien VPN itu sendiri, jadi penyuntingan profil atau pemeriksaan kredensial tidak akan membantu.
Kode status memisahkan keluarga ini dari kerusakan biasa. Unit yang keluar dengan status=203/EXEC tidak pernah memulai proses; unit yang mulai lalu keluar dengan status=1 mungkin gagal pada autentikasi, DNS, atau perutean. Baca kode sebelum membaca log klien, karena pada kasus pertama log klien akan kosong.
Jalur di jurnal adalah jalur yang dipakai systemd, bukan tentu jalur yang Anda sunting. Berkas drop-in dan keluaran generator dapat menimpa berkas vendor, dan daemon-reload yang basi meninggalkan baris lama di memori. Karena itu diagnostik pertama adalah menanyakan kepada systemd apa yang dianggapnya perintah, bukan membuka berkas yang Anda ingat telah diubah.
Tiga tempat jalur biner dituliskan
Klien VPN yang dipasang dari paket distribusi, skrip vendor, dan tarball rilis dapat mendarat di tiga prefiks berbeda. Unit, aturan hak istimewa, dan penginstal masing-masing mencatat satu dari prefiks itu, dan kegagalan muncul ketika dua dari tiga tidak cocok.
| Record | Common value | How to read it |
|---|---|---|
| Unit or drop-in | /usr/local/bin/vpnclient | systemctl cat vpnclient.service |
| Installed binary | /usr/bin/vpnclient | command -v vpnclient, then ls -l the result |
| Sudoers grant | /opt/vpnclient/bin/vpnclient | sudo grep -r vpnclient /etc/sudoers.d/ |
Ketidakcocokan konkret tampak seperti ini: skrip vendor memasang ke /usr/local/bin, tarball diekstrak di bawah /opt, dan unit masih menyebut jalur /usr/bin lama dari paket sebelumnya. Hanya satu dari berkas itu yang ada, dan jarang yang ada di ExecStart.
Putuskan jalur mana yang kanonis sebelum mengubah salah satu berkas. Jika paket distribusi memiliki biner itu, jalur paket adalah yang kanonis dan unit harus mengikutinya. Jika skrip vendor yang memilikinya, aturan yang sama berlaku untuk prefiks vendor. Menyalin biner antarprefiks menciptakan dua salinan yang menyimpang pada pemutakhiran berikutnya.
Ketika perintah dalam tanda kutip menjadi nama berkas
Mode kegagalan kedua bersembunyi di balik baris jurnal yang sama. Seseorang menulis ini ke unit dan mengharapkan klien terhubung saat boot:
ExecStart=/usr/bin/"vpnclient connect office"systemd memecah nilai menjadi kata, sehingga kata pertama menjadi /usr/bin/vpnclient connect office dengan tanda kutip dihapus sebagai sintaks pengelompokan. Lalu kernel mencari berkas yang namanya mengandung spasi, dan berkas itu tidak ada. Kesalahannya identik dengan biner yang hilang meskipun biner itu terpasang.
Bentuk yang didukung adalah berkas yang benar-benar dapat dieksekusi diikuti argumen terpisah, misalnya ExecStart=/usr/bin/vpnclient connect office. Jika alur kerja benar-benar membutuhkan pipa atau rantai, letakkan di skrip dan panggil skrip itu, karena ExecStart tidak memiliki &&, tidak memiliki pipa, dan tidak memiliki perluasan glob.
Perbaiki unit, bukan sistem berkas
Perbaikan yang menggoda adalah tautan simbolik dari jalur yang diharapkan ke biner sebenarnya. Itu berfungsi sampai paket diperbarui dan tautan menunjuk ke berkas yang dihapus, atau sampai label SELinux tidak lagi cocok dengan target. Lebih baik menyunting unit melalui drop-in agar berkas vendor tetap utuh dan pemutakhiran tetap dapat diprediksi.
Aturan hak istimewa harus cocok dengan jalur yang sama dan subperintah yang sama. Entri sudoers untuk /usr/local/bin/vpnclient tidak memberi wewenang untuk /usr/bin/vpnclient, dan entri yang mengizinkan setiap argumen membiarkan proses lokal mana pun mengonfigurasi ulang atau menghentikan terowongan. Berikan dua kata kerja yang dibutuhkan unit dan jauhkan pembongkaran darinya jika menghentikan layanan sudah menutup antarmuka.
Di sinilah perbandingan berbuah: unit, basis data paket, dan sudoers semestinya menyebut satu jalur. Bila begitu, kesalahan EXEC hilang tanpa reboot dan tanpa salinan biner di lokasi ketiga.
Buktikan perintah yang diurai sebelum reboot
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-pagersystemctl show adalah keluaran yang menentukan karena mencetak argv yang benar-benar diurai systemd, termasuk drop-in apa pun. systemd-analyze verify menangkap jalur yang hilang atau tidak dapat dieksekusi sebelum Anda memulai ulang, dan perintah status setelah mulai ulang memberi tahu apakah proses itu kini ada.
Jika unit mulai lalu gagal, Anda telah meninggalkan keluarga EXEC dan masuk ke penanganan kesalahan klien itu sendiri. Periksa jurnal untuk pesan klien, bukan kegagalan execve lain. Simpan diff unit dan diff sudoers bersama dalam catatan perubahan agar pemutakhiran berikutnya tidak diam-diam mengembalikan jalur yang terbelah.