I går virket tunnelen, og i morges er unit-en død med Failed at step EXEC spawning /usr/local/bin/vpnclient i journalen. Legitimasjon, ruter og kontoen dukker aldri opp i den setningen. systemd løste ExecStart til en sti, ba kjernen om å kjøre den, og kjernen nektet, oftest fordi det ikke finnes noe på den stien eller fordi filen ikke er kjørbar. Behandle feilen som et fil- og argv-problem til den parsede kommandoen beviser det motsatte.

Hvorfor EXEC feiler før autentiseringen starter

systemd kjører ikke ExecStart gjennom et skall. Den forker, bygger en argumentvektor fra linjen og kaller execve på det første elementet. Hvis det kallet feiler, når tjenesten aldri inn i VPN-klientens egen kode, så verken profilredigering eller kontroll av legitimasjon kan hjelpe.

Statuskoden skiller denne familien fra vanlige krasj. En unit som avslutter med status=203/EXEC har aldri startet en prosess; en unit som starter og deretter avslutter med status=1 har kanskje feilet på autentisering, DNS eller ruting. Les koden før du leser klientloggen, for i det første tilfellet vil klientloggen være tom.

Stien i journalen er den systemd brukte, ikke nødvendigvis den du redigerte. Drop-ins og generatorutdata kan overstyre leverandørens fil, og en utdatert daemon-reload lar den gamle linjen bli i minnet. Derfor er den første diagnosen å spørre systemd hva den mener kommandoen er, i stedet for å åpne filen du husker at du endret.

Tre steder der stien til binærfilen står skrevet

En VPN-klient installert fra en distribusjonspakke, et leverandørskript og en tarball fra en utgivelse kan havne i tre forskjellige prefikser. Unit-en, privilegieregelen og installatøren registrerte hver sitt av disse prefiksene, og feilen vises når to av de tre ikke stemmer.

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/

En konkret uoverensstemmelse ser slik ut: leverandørskriptet installerer til /usr/local/bin, tarballen ble pakket ut under /opt, og unit-en nevner fortsatt den gamle /usr/bin-stien fra en tidligere pakke. Bare én av disse filene finnes, og det er sjelden den i ExecStart.

Avgjør hvilken sti som er kanonisk før du endrer noen av filene. Hvis distribusjonspakken eier binærfilen, er pakkestien kanonisk, og unit-en skal følge den. Hvis leverandørskriptet eier den, gjelder samme regel for leverandørens prefiks. Å kopiere en binærfil mellom prefikser lager to kopier som glir fra hverandre ved neste oppgradering.

Når en kommando i anførselstegn blir et filnavn

En andre feilmodus skjuler seg bak den samme journallinjen. Noen skriver dette i unit-en og forventer at klienten kobler til under oppstart:

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

systemd deler verdien i ord, slik at det første ordet blir /usr/bin/vpnclient connect office, mens anførselstegnene fjernes som grupperingssyntaks. Deretter leter kjernen etter en fil hvis navn inneholder mellomrom, og det finnes ingen. Feilen er identisk med en manglende binærfil, selv om binærfilen er installert.

Den støttede formen er en ekte kjørbar fil etterfulgt av separate argumenter, for eksempel ExecStart=/usr/bin/vpnclient connect office. Hvis arbeidsflyten virkelig trenger en pipeline eller en kjede, legg den i et skript og kall skriptet, fordi ExecStart ikke har &&, ingen rør og ingen glob-utvidelse.

Reparer unit-en, ikke filsystemet

Den fristende reparasjonen er en symbolsk lenke fra den forventede stien til den ekte binærfilen. Den virker til pakken oppdateres og lenken peker på en fjernet fil, eller til en SELinux-etikett ikke lenger passer til målet. Foretrekk å redigere unit-en via en drop-in, slik at leverandørens fil forblir urørt og oppgraderinger forblir forutsigbare.

Privilegieregelen må samsvare med den samme stien og de samme underkommandoene. En sudoers-oppføring for /usr/local/bin/vpnclient autoriserer ikke /usr/bin/vpnclient, og en oppføring som tillater alle argumenter, lar enhver lokal prosess rekonfigurere eller stoppe tunnelen. Gi de to verbene unit-en trenger, og hold nedrivingen utenfor hvis stopping av tjenesten allerede lukker grensesnittet.

Det er her sammenligningen lønner seg: unit-en, pakkedatabasen og sudoers bør alle nevne én sti. Når de gjør det, forsvinner EXEC-feilen uten omstart og uten en kopi av binærfilen på et tredje sted.

Bevis den parsede kommandoen før omstart

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 er det avgjørende utdataet fordi det skriver ut argv-en systemd faktisk parsede, inkludert enhver drop-in. systemd-analyze verify fanger opp en manglende eller ikke-kjørbar sti før du starter på nytt, og statuskommandoen etter omstarten forteller om prosessen nå finnes.

Hvis unit-en starter og deretter feiler, har du forlatt EXEC-familien og gått inn i klientens egen feilhåndtering. Se i journalen etter klientens melding, ikke etter nok en execve-feil. Hold unit-diffen og sudoers-diffen sammen i endringsloggen, slik at neste oppgradering ikke stille gjeninnfører den delte stien.

Relaterte artikler