VPN-diens faal by EXEC: vergelyk unit, binary en sudoers
Om by stap EXEC te faal beteken systemd kon nie die binary begin nie. Vergelyk die unit-pad, die geïnstalleerde pad en die sudoers-toestemming voordat jy iets wysig.
Gister het die tonnel gewerk, en vanoggend is die unit dood met Failed at step EXEC spawning /usr/local/bin/vpnclient in die joernaal. Inloggegewens, roetes en die rekening kom nooit in daardie sin voor nie. systemd het ExecStart na ’n pad opgelos, die kernel gevra om dit uit te voer, en die kernel het geweier, meestal omdat niks op daardie pad bestaan nie of omdat dit nie uitvoerbaar is nie. Behandel die fout as ’n lêer-en-argv-probleem totdat die ontlede opdrag die teendeel bewys.
Waarom EXEC misluk voordat verifikasie begin
systemd voer nie ExecStart deur ’n dop uit nie. Dit skep ’n kindproses, bou ’n argumentvektor uit die reël en roep execve op die eerste element. As daardie oproep misluk, bereik die diens nooit die VPN-kliënt se eie kode nie, so geen hoeveelheid profielwysiging of kontrole van aanmeldgegewens kan help nie.
Die statuskode skei hierdie familie van gewone ineenstortings. ’n Unit wat met status=203/EXEC uitgaan, het nooit ’n proses begin nie; ’n unit wat begin en dan met status=1 kon misluk het op verifikasie, DNS of roetering. Lees die kode voordat jy die kliëntlog lees, want die kliëntlog sal in die eerste geval leeg wees.
Die pad in die joernaal is die een wat systemd gebruik het, nie noodwendig die een wat jy gewysig het nie. Drop-ins en generator-uitsette kan die verskaffer se lêer oorheers, en ’n verouderde daemon-reload laat die ou reël in die geheue. Daarom is die eerste diagnose om systemd te vra wat hy dink die opdrag is, eerder as om die lêer oop te maak wat jy onthou jy verander het.
Drie plekke waar die binary-pad neergeskryf word
’n VPN-kliënt wat uit ’n verspreidingspakket, ’n verskafferskrip en ’n vrystellings-tarball geïnstalleer is, kan in drie verskillende voorvoegsels beland. Die unit, die bevoegdheidsreël en die installeerder het elkeen een van daardie voorvoegsels aangeteken, en die fout verskyn wanneer twee van die drie nie saamstem nie.
| 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/ |
’n Konkrete wanaanpassing lyk so: die verskafferskrip installeer na /usr/local/bin, die tarball is onder /opt uitgepak, en die unit noem steeds die ou /usr/bin-pad uit ’n vorige pakket. Net een van daardie lêers bestaan, en dit is selde die een in ExecStart.
Besluit watter pad kanoniek is voordat jy een van die lêers verander. As die verspreidingspakket die binary besit, is die pakketpad kanoniek en die unit moet dit volg. As die verskafferskrip dit besit, geld dieselfde reël vir die verskaffervoorvoegsel. Om ’n binary tussen voorvoegsels te kopieer, skep twee kopieë wat by die volgende opgradering uitmekaar dryf.
Wanneer ’n aangehaalde opdrag ’n lêernaam word
’n Tweede foutmodus skuil agter dieselfde joernaalreël. Iemand skryf dit in die unit en verwag dat die kliënt tydens die boot sal konnekteer:
ExecStart=/usr/bin/"vpnclient connect office"systemd verdeel die waarde in woorde, so die eerste woord word /usr/bin/vpnclient connect office met die aanhalingstekens as groeperingssintaksis verwyder. Die kernel soek dan na ’n lêer wie se naam spasies bevat, en dit bestaan nie. Die fout is identies aan ’n ontbrekende binary, selfs al is die binary geïnstalleer.
Die ondersteunde vorm is ’n egte uitvoerbare lêer gevolg deur afsonderlike argumente, byvoorbeeld ExecStart=/usr/bin/vpnclient connect office. As die werkstroom werklik ’n pyplyn of ’n ketting nodig het, plaas dit in ’n skrip en roep die skrip, want ExecStart het geen && nie, geen pype en geen glob-uitbreiding nie.
Maak die unit reg, nie die lêerstelsel nie
Die aanloklike herstel is ’n sagte skakel van die verwagte pad na die werklike binary. Dit werk totdat die pakket opdateer en die skakel na ’n verwyderde lêer wys, of totdat ’n SELinux-etiket nie meer by die teiken pas nie. Verkies om die unit deur ’n drop-in te wysig, sodat die verskaffer se lêer onaangeraak bly en opgraderings voorspelbaar bly.
Die bevoegdheidsreël moet by dieselfde pad en dieselfde subopdragte pas. ’n Sudoers-inskrywing vir /usr/local/bin/vpnclient magtig nie /usr/bin/vpnclient nie, en ’n inskrywing wat elke argument toelaat, laat enige plaaslike proses die tonnel herkonfigureer of stop. Verleen die twee werkwoorde wat die unit nodig het en hou die afbreek daaruit as die staking van die diens reeds die koppelvlak sluit.
Dit is waar die vergelyking vrugte afwerp: die unit, die pakketdatabasis en sudoers moet almal een pad noem. Wanneer hulle dit doen, verdwyn die EXEC-fout sonder ’n herlaai en sonder ’n kopie van die binary op ’n derde plek.
Bewys die ontlede opdrag voor herlaai
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 is die beslissende uitset, want dit druk die argv wat systemd werklik ontleed het, insluitend enige drop-in. systemd-analyze verify vang ’n ontbrekende of nie-uitvoerbare pad voordat jy herbegin, en die statusopdrag ná die herbegin vertel jou of die proses nou bestaan.
As die unit begin en dan misluk, het jy die EXEC-familie verlaat en die kliënt se eie foutafhandeling binnegegaan. Kyk in die joernaal vir die kliënt se boodskap, nie vir nog ’n execve-mislukking nie. Hou die unit-diff en die sudoers-diff saam in die veranderingsrekord, sodat die volgende opgradering nie die gesplete pad stilweg weer invoer nie.