I går virkede tunnelen, og i morges er unit død med Failed at step EXEC spawning /usr/local/bin/vpnclient i journalen. Legitimationsoplysninger, ruter og kontoen optræder aldrig i den sætning. systemd opløste ExecStart til en sti, bad kernen om at køre den, og kernen afviste, oftest fordi der ikke findes noget på den sti, eller fordi filen ikke er eksekverbar. Behandl fejlen som et fil- og argv-problem, indtil den parsede kommando beviser det modsatte.

Hvorfor EXEC fejler, før godkendelsen begynder

systemd kører ikke ExecStart gennem et shell. Den laver en fork, bygger en argumentvektor ud fra linjen og kalder execve på det første element. Hvis kaldet fejler, når tjenesten aldrig ind i VPN-klientens egen kode, så ingen profilredigering eller kontrol af legitimationsoplysninger kan hjælpe.

Statuskoden adskiller denne familie fra almindelige nedbrud. En unit, der afslutter med status=203/EXEC, har aldrig startet en proces; en unit, der starter og derefter afslutter med status=1 er måske fejlet på godkendelse, DNS eller routing. Læs koden, før du læser klientloggen, for i det første tilfælde vil klientloggen være tom.

Stien i journalen er den, systemd brugte, ikke nødvendigvis den, du redigerede. Drop-ins og generatoroutput kan tilsidesætte leverandørens fil, og en forældet daemon-reload efterlader den gamle linje i hukommelsen. Derfor er den første diagnostik at spørge systemd, hvad den mener kommandoen er, i stedet for at åbne den fil, du husker at have ændret.

Tre steder, hvor binærfilens sti står skrevet

En VPN-klient installeret fra en distributionspakke, et leverandørscript og en tarball fra en udgivelse kan ende i tre forskellige præfikser. Unit, privilegieregel og installer registrerede hver ét af disse præfikser, og fejlen vises, når to af de tre ikke stemmer overens.

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 sådan ud: leverandørscriptet installerer til /usr/local/bin, tarballen blev pakket ud under /opt, og unit nævner stadig den gamle /usr/bin-sti fra en tidligere pakke. Kun én af disse filer findes, og det er sjældent den i ExecStart.

Afgør, hvilken sti der er kanonisk, før du ændrer nogen af filerne. Hvis distributionspakken ejer binærfilen, er pakkens sti kanonisk, og unit skal følge den. Hvis leverandørscriptet ejer den, gælder samme regel for leverandørens præfiks. At kopiere en binærfil mellem præfikser skaber to kopier, der glider fra hinanden ved næste opgradering.

Når en kommando i citationstegn bliver et filnavn

En anden fejltilstand skjuler sig bag den samme journallinje. Nogen skriver dette i unit og forventer, at klienten opretter forbindelse under opstart:

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

systemd deler værdien i ord, så det første ord bliver /usr/bin/vpnclient connect office, når citationstegnene fjernes som grupperingssyntaks. Derefter leder kernen efter en fil, hvis navn indeholder mellemrum, og den findes ikke. Fejlen er identisk med en manglende binærfil, selv om binærfilen er installeret.

Den understøttede form er en rigtig eksekverbar fil efterfulgt af separate argumenter, for eksempel ExecStart=/usr/bin/vpnclient connect office. Hvis arbejdsgangen virkelig kræver en pipeline eller en kæde, så læg den i et script og kald scriptet, for ExecStart har ingen &&, ingen pipes og ingen glob-udvidelse.

Ret unit, ikke filsystemet

Den fristende reparation er et symbolsk link fra den forventede sti til den rigtige binærfil. Det virker, indtil pakken opdateres og linket peger på en fjernet fil, eller indtil en SELinux-label ikke længere passer til målet. Foretræk at redigere unit via en drop-in, så leverandørens fil forbliver urørt, og opgraderinger forbliver forudsigelige.

Privilegiereglen skal matche den samme sti og de samme underkommandoer. En sudoers-post for /usr/local/bin/vpnclient tillader ikke /usr/bin/vpnclient, og en post, der tillader alle argumenter, lader enhver lokal proces omkonfigurere eller stoppe tunnelen. Giv de to verber, som unit har brug for, og hold nedtagning uden for den, hvis stop af tjenesten allerede lukker grænsefladen.

Det er her sammenligningen betaler sig: unit, pakkedatabasen og sudoers bør alle nævne én sti. Når de gør det, forsvinder EXEC-fejlen uden genstart og uden en kopi af binærfilen på et tredje sted.

Bevis den parsede kommando før genstart

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 afgørende output, fordi det udskriver den argv, systemd faktisk parsede, inklusive enhver drop-in. systemd-analyze verify fanger en manglende eller ikke-eksekverbar sti, før du genstarter, og statuskommandoen efter genstart fortæller, om processen nu findes.

Hvis unit starter og derefter fejler, har du forladt EXEC-familien og er trådt ind i klientens egen fejlhåndtering. Se i journalen efter klientens besked, ikke efter endnu en execve-fejl. Hold unit-diffen og sudoers-diffen sammen i ændringsregistret, så næste opgradering ikke lydløst genindfører den delte sti.

Relaterede artikler