Včeraj je tunel deloval, danes zjutraj pa je unit mrtev, v journalu je Failed at step EXEC spawning /usr/local/bin/vpnclient. Poverilnice, poti in račun se v tem stavku nikoli ne pojavijo. systemd je ExecStart razrešil v pot, jedro prosil, naj jo izvede, in jedro je zavrnilo, najpogosteje zato, ker na tej poti ni ničesar ali datoteka ni izvedljiva. Napako obravnavajte kot težavo datoteke in argv, dokler analizirani ukaz ne dokaže nasprotnega.

Zakaj EXEC odpove, preden se začne preverjanje pristnosti

systemd ne zažene ExecStart prek lupine. Naredi fork, iz vrstice zgradi vektor argumentov in pokliče execve na prvi element. Če ta klic ne uspe, storitev nikoli ne doseže lastne kode odjemalca VPN, zato urejanje profila ali preverjanje poverilnic ne more pomagati.

Koda stanja ločuje to družino od običajnih sesutij. Unit, ki se konča s status=203/EXEC, ni nikoli zagnal procesa; unit, ki se zažene in nato konča s status=1 je morda odpovedal pri preverjanju pristnosti, DNS ali usmerjanju. Preberite kodo pred dnevnikom odjemalca, ker bo v prvem primeru dnevnik odjemalca prazen.

Pot v journalu je tista, ki jo je uporabil systemd, ne nujno tista, ki ste jo uredili. Datoteke drop-in in izhod generatorja lahko prepišejo datoteko dobavitelja, zastarel daemon-reload pa pusti staro vrstico v pomnilniku. Zato je prva diagnostika vprašati systemd, kaj meni, da je ukaz, namesto da odprete datoteko, ki se je spomnite kot spremenjene.

Tri mesta, kjer je zapisana pot do binarne datoteke

Odjemalec VPN, nameščen iz paketa distribucije, skripta dobavitelja in tarballa izdaje, lahko pristane v treh različnih predponah. Unit, pravilo privilegijev in namestitveni program so vsak zabeležili eno od teh predpon, napaka pa se pojavi, ko se dve od treh ne ujemata.

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/

Konkretno neskladje je videti takole: skript dobavitelja namešča v /usr/local/bin, tarball je bil razpakiran pod /opt, unit pa še vedno navaja staro pot /usr/bin iz prejšnjega paketa. Obstaja le ena od teh datotek in redko je to tista v ExecStart.

Preden spremenite katero od datotek, določite, katera pot je kanonična. Če je binarna datoteka last paketa distribucije, je kanonična pot paketa in unit ji mora slediti. Če je last skripta dobavitelja, velja isto pravilo za predpono dobavitelja. Kopiranje binarne datoteke med predponami ustvari dve kopiji, ki se ob naslednji posodobitvi razhajata.

Ko ukaz v narekovajih postane ime datoteke

Drugi način odpovedi se skriva za isto vrstico v journalu. Nekdo to zapiše v unit in pričakuje, da se bo odjemalec povezal med zagonom:

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

systemd razdeli vrednost na besede, zato prva beseda postane /usr/bin/vpnclient connect office, narekovaji pa se odstranijo kot sintaksa združevanja. Nato jedro išče datoteko, katere ime vsebuje presledke, in takšne ni. Napaka je enaka kot pri manjkajoči binarni datoteki, čeprav je datoteka nameščena.

Podprta oblika je resnična izvedljiva datoteka, ki ji sledijo ločeni argumenti, na primer ExecStart=/usr/bin/vpnclient connect office. Če delovni tok resnično potrebuje cevovod ali verigo, ga dajte v skript in pokličite skript, ker ExecStart nima &&, nima cevi in nima razširitve glob.

Popravite unit, ne datotečnega sistema

Vabljiva popravka je simbolna povezava z pričakovane poti na pravo binarno datoteko. Deluje, dokler se paket ne posodobi in povezava ne kaže na odstranjeno datoteko, ali dokler se oznaka SELinux ne preneha ujemati s ciljem. Raje uredite unit prek drop-in, da datoteka dobavitelja ostane nedotaknjena in posodobitve ostanejo predvidljive.

Pravilo privilegijev se mora ujemati z isto potjo in istimi podukazi. Vnos v sudoers za /usr/local/bin/vpnclient ne pooblasti /usr/bin/vpnclient, vnos, ki dovoljuje vsak argument, pa omogoči vsakemu lokalnemu procesu, da prekonfigurira ali ustavi tunel. Dajte unitu dva glagola, ki jih potrebuje, in demontažo držite zunaj njega, če ustavitev storitve že zapre vmesnik.

Tu se primerjava obrestuje: unit, baza paketov in sudoers bi morali navesti eno pot. Ko jo, napaka EXEC izgine brez ponovnega zagona in brez kopije binarne datoteke na tretjem mestu.

Dokažite analizirani ukaz pred ponovnim zagonom

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 je odločilen izhod, ker izpiše argv, ki ga je systemd resnično analiziral, vključno z vsakim drop-inom. systemd-analyze verify ujame manjkajočo ali neizvedljivo pot pred ponovnim zagonom, statusni ukaz po ponovnem zagonu pa pove, ali proces zdaj obstaja.

Če se unit zažene in nato odpove, ste zapustili družino EXEC in vstopili v lastno obdelavo napak odjemalca. V journalu iščite sporočilo odjemalca, ne še ene odpovedi execve. Diff unita in diff sudoers hranite skupaj v zapisu spremembe, da naslednja posodobitev ne bo tiho vrnila razcepljene poti.

Sorodni članki