VPN-dienst faalt bij EXEC: vergelijk unit, binair bestand en sudoers
Falen bij stap EXEC betekent dat systemd het binaire bestand niet kon starten. Vergelijk het pad in de unit, het geïnstalleerde pad en de sudoers-toestemming voordat u iets wijzigt.
Gisteren werkte de tunnel, en vanmorgen is de unit dood met Failed at step EXEC spawning /usr/local/bin/vpnclient in het journal. Inloggegevens, routes en het account komen nooit in die zin voor. systemd heeft ExecStart naar een pad vertaald, de kernel gevraagd het uit te voeren, en de kernel weigerde, meestal omdat er op dat pad niets bestaat of omdat het bestand niet uitvoerbaar is. Behandel de fout als een bestands- en argv-probleem tot het geparseerde commando het tegendeel bewijst.
Waarom EXEC faalt voordat de authenticatie begint
systemd voert ExecStart niet via een shell uit. Het forkt, bouwt een argumentvector uit de regel en roept execve aan op het eerste element. Als die aanroep mislukt, bereikt de dienst nooit de eigen code van de VPN-client, dus geen profielbewerking of controle van inloggegevens kan helpen.
De statuscode scheidt deze familie van gewone crashes. Een unit die met status=203/EXEC eindigt, heeft nooit een proces gestart; een unit die start en daarna met status=1 eindigt, is mogelijk mislukt op authenticatie, DNS of routering. Lees de code voordat u het clientlog leest, want in het eerste geval blijft het clientlog leeg.
Het pad in het journal is het pad dat systemd gebruikte, niet noodzakelijk het pad dat u hebt bewerkt. Drop-ins en generatoruitvoer kunnen het bestand van de leverancier overschrijven, en een verouderde daemon-reload laat de oude regel in het geheugen staan. Daarom is de eerste diagnose systemd vragen wat het voor het commando houdt, in plaats van het bestand te openen waarvan u zich herinnert dat u het hebt gewijzigd.
Drie plaatsen waar het pad van het binaire bestand staat
Een VPN-client die uit een distributiepakket, een leveranciersscript en een release-tarball is geïnstalleerd, kan in drie verschillende prefixen terechtkomen. De unit, de privilegesregel en het installatieprogramma hebben elk een van die prefixen vastgelegd, en de fout verschijnt wanneer twee van de drie niet overeenkomen.
| 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/ |
Een concreet verschil ziet er zo uit: het leveranciersscript installeert naar /usr/local/bin, de tarball is uitgepakt onder /opt, en de unit noemt nog steeds het oude pad /usr/bin uit een eerder pakket. Slechts een van die bestanden bestaat, en het is zelden het bestand in ExecStart.
Bepaal welk pad canoniek is voordat u een van de bestanden wijzigt. Als het distributiepakket het binaire bestand bezit, is het pakketpad canoniek en moet de unit dat volgen. Als het leveranciersscript het bezit, geldt dezelfde regel voor het prefix van de leverancier. Een binair bestand tussen prefixen kopiëren levert twee kopieën op die bij de volgende upgrade uiteenlopen.
Wanneer een commando tussen aanhalingstekens een bestandsnaam wordt
Een tweede faalmodus verbergt zich achter dezelfde journalregel. Iemand schrijft dit in de unit en verwacht dat de client tijdens het opstarten verbinding maakt:
ExecStart=/usr/bin/"vpnclient connect office"systemd splitst de waarde in woorden, waardoor het eerste woord /usr/bin/vpnclient connect office wordt, terwijl de aanhalingstekens als groeperingssyntaxis verdwijnen. Daarna zoekt de kernel een bestand waarvan de naam spaties bevat, en dat bestaat niet. De fout is identiek aan een ontbrekend binair bestand, hoewel het bestand is geïnstalleerd.
De ondersteunde vorm is een echt uitvoerbaar bestand gevolgd door afzonderlijke argumenten, bijvoorbeeld ExecStart=/usr/bin/vpnclient connect office. Als de werkstroom echt een pijplijn of een keten nodig heeft, zet die in een script en roep het script aan, want ExecStart heeft geen &&, geen pipes en geen glob-expansie.
Repareer de unit, niet het bestandssysteem
De verleidelijke reparatie is een symbolische koppeling van het verwachte pad naar het echte binaire bestand. Die werkt tot het pakket wordt bijgewerkt en de koppeling naar een verwijderd bestand wijst, of tot een SELinux-label niet meer bij het doel past. Bewerk de unit liever via een drop-in, zodat het bestand van de leverancier onaangeroerd blijft en upgrades voorspelbaar blijven.
De privilegesregel moet bij hetzelfde pad en dezelfde subcommando’s passen. Een sudoers-regel voor /usr/local/bin/vpnclient machtigt /usr/bin/vpnclient niet, en een regel die elk argument toestaat, laat elk lokaal proces de tunnel herconfigureren of stoppen. Geef de twee werkwoorden die de unit nodig heeft en houd het afbreken erbuiten als het stoppen van de dienst de interface al sluit.
Hier loont de vergelijking: de unit, de pakketdatabase en sudoers zouden alle één pad moeten noemen. Als dat zo is, verdwijnt de EXEC-fout zonder herstart en zonder een kopie van het binaire bestand op een derde plek.
Bewijs het geparseerde commando voor de herstart
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 de beslissende uitvoer omdat het de argv toont die systemd werkelijk heeft geparseerd, inclusief elke drop-in. systemd-analyze verify vangt een ontbrekend of niet-uitvoerbaar pad voordat u herstart, en de statusopdracht na de herstart vertelt of het proces nu bestaat.
Als de unit start en daarna faalt, hebt u de EXEC-familie verlaten en bent u in de eigen foutafhandeling van de client beland. Zoek in het journal naar de melding van de client, niet naar nog een execve-fout. Bewaar de unit-diff en de sudoers-diff samen in het wijzigingsregister, zodat de volgende upgrade het gesplitste pad niet stilzwijgend opnieuw invoert.