ExecStart er ikke et shell: ret en VPN-hjælpeunit op
ExecStart kører et program med argumenter, ikke en shell-pipeline. Brug en eksplicit fortolker eller et rigtigt script, og verificér derefter uniten og læs journalen.
Kopiér en fungerende kommandolinje ind i ExecStart, genindlæs, og uniten fejler eller afslutter lydløst, fordi argumenterne behandles som filnavne. Der er intet i stykker i systemd. ExecStart er en argumentliste, ikke et shell, så pipes, omdirigering og betingelser mister deres betydning i det øjeblik, de forlader din terminal. Beslut hvor shellen hører hjemme, og skriv derefter en unit, der præcist siger, hvad der skal køres.
Hvorfor pipelinen i ExecStart ikke gør noget
Når en kommando skrives i en terminal, parser shellen den først. Den bygger en pipeline, åbner filer til omdirigering og udvider variabler, før noget program starter. systemd gør intet af det: den opdeler ExecStart efter sine egne regler og kører det resulterende program med de argumenter. Derfor ankommer > som et bogstaveligt argument, og | gives videre til programmet i stedet for at forbinde to processer. Uniten opfører sig ikke forkert; syntaksen betød noget andet.
Det er bevidst og ikke sjusk, fordi forudsigelig argumenthåndtering er det, der gør units reviderbare. Det overrasker kun dem, der antager, at der er et shell til stede.
Skriv en unit, der præcist siger, hvad der kører
Begynd med en lille unit, hvis formål er synligt i journalen, så parserproblemer holdes adskilt fra tunnelproblemer. Denne rapporterer kun en binærs version.
[Unit]
Description=Report the installed OpenVPN version
[Service]
Type=oneshot
ExecStart=/usr/sbin/openvpn --version
StandardOutput=journal
StandardError=journalStien er en pladsholder, så indsæt den binær, der faktisk er installeret. Type=oneshot passer til en kommando, der kører til afslutning, og journalindstillingerne lægger dens output, hvor du kan læse det uden terminal. Der er bevidst ingen installationssektion, så uniten kaldes i hånden i stedet for at blive aktiveret ved opstart. Validér filen, før du starter den, fordi en tastefejl i et direktivnavn fejler anderledes end en tastefejl i stien.
systemd-analyze verify /etc/systemd/system/openvpn-version.service
systemctl start openvpn-version.serviceHold shell-logik i et script
Når en hjælper virkelig har brug for betinget logik, læg den logik i et script og kald det eksplicit. Scriptet skal have en fortolkerlinje, køretilladelse og exitkoder, som tjenesten kan rapportere. At starte /bin/sh -c med en kommando i anførselstegn virker, men det skjuler anførselstegnsregler inde i en unit og gør gennemgang sværere. Et navngivet script kan testes i hånden og senere erstattes uden at redigere uniten. Stol ikke på den interaktive brugers shell-profil, fordi en tjeneste starter med sit eget miljø.
Sæt WorkingDirectory, når relative stier betyder noget, og send miljø videre gennem unitens understøttede direktiver i stedet for at eksportere det i en terminal. Hemmeligheder hører til beskyttede filer eller legitimationsoplysninger, ikke i argumentlister, som journalen kan registrere.
Kontrollér den unit, der faktisk findes
Drop-in-filer ændrer adfærd uden at røre den fil, du husker, du redigerede. Læs, hvad manageren indlæste, og hvad den sidste kørsel rapporterede.
systemctl cat vpn-helper.service
journalctl -u vpn-helper.service -n 20 --no-pagerUnit-dumpet inkluderer drop-in-filer i indlæsningsrækkefølge, og det er typisk der, en uventet ExecStart kommer fra. Genindlæs manageren efter enhver ændring, og bekræft, at den nye definition er det, som systemctl cat udskriver. Journalen viser den præcise kommandolinje og exitstatus, hvilket adskiller et argumentproblem fra en manglende binær eller en tilladelsesfejl. Beslut derefter, om hjælperen hører til den eksisterende VPN-livscyklus, eller skal forblive en manuel diagnostik, fordi en anden baggrundstunnelproces skaber en konkurrerende ejer.
En unit, der udskriver det rigtige output på kommando, er en god første milepæl. Den er endnu ikke en tunnel og bør ikke foregive at være det.