Tilfeldig OpenVPN-val i systemd: kvifor ExecStart feilar
systemd er ikkje eit skal, så ein blanda kopi inne i ExecStart døyr. Flytt valet til ExecStartPre, eller la OpenVPN velje ein tenar sjølv.
Førti .ovpn-filer for eitt land kjem frå ein leverandør, og planen ser openberr ut: kopier ein tilfeldig på plass, og start deretter tunellen. Skriven som ein pipeline inne i ExecStart døyr den planen ved oppstart med ein statuskode som ikkje forklarer noko. Unit-fila er ikkje eit skript, og rettinga er anten å hente inn eit skal eksplisitt eller å slutte heilt å velje filer.
Symptomet: ein unit som startar og døyr med ein gong
Statusen viser at tenesta feila i løpet av ein brøkdel av eit sekund, og journal-linja namngjev ein kommando som ingen skal nokon gong ville ha motteke. Ingenting om tunellen viser seg, fordi tunellen aldri byrja.
Å lese den nøyaktige kommandolinja frå journalen er den raskaste måten å stadfeste dette på. systemd gjev att det han køyrde, og strengen vil vise pipeline-teikna som bokstavelege argument i staden for som operatorar.
Kvifor ExecStart ikkje kan køyre ein pipeline
systemd deler opp kommandolinja sjølv, brukar si eiga sitat- og variabelsubstitusjon, og køyrer deretter resultatet direkte. Pipes, omdirigering, glob-utviding frå eit skal og kommandosubstitusjon er rett og slett ikkje ein del av denne grammatikken. Det er eit designval og ikkje ei utelating: ein unit seier deklarativt kva som skal køyrast, og skal-logikk høyrer heime i eit skript som uniten kallar. Begge rettingane følgjer av dette, og ingen av dei krev at uniten får fleire rettar.
Det forklarer også den misvisande utgangskoden. Det første argumentet blir handsama som binæren, så ei feilforma linje feilar før noko av logikken din køyrer.
Gjer valet i ExecStartPre
Den direkte rettinga er eit førebuingssteg som kallar eit skal eksplisitt, og held valet og starten i same unit slik at ein feil i den eine ikkje kan la den andre køyre åleine.
[Service]
Type=notify
ExecStartPre=/bin/bash -c "ls /etc/openvpn/profiles/au* | shuf -n 1 | xargs -r -I{} cp -f {} /etc/openvpn/%i.conf"
ExecStart=/usr/sbin/openvpn --config /etc/openvpn/%i.conf
Tre detaljar avgjer om dette overlever møtet med ei ekte maskin. Namngjeving er den første fella: systemd erstattar %i allereie ved parsing av uniten, lenge før bash køyrer, så spesifikatoren må stå utanfor enkle hermeteikn. xargs -r hindrar cp i å køyre utan argument når globen ikkje treff noko. Og eit mislukka førebuingssteg stoppar uniten, og det er det rette utfallet: å starte med gårsdagens konfigurasjon er verre enn å ikkje starte. Eit tilfeldig val som alltid tek same fil er vanlegvis ikkje uflaks. Sjekk om den kopierte fila blir overstyrt av ein pakkeoppdatering, eller om globen berre treff éi forelda oppføring.
Eller la OpenVPN velje endepunktet
OpenVPN kan allereie halde fleire endepunkt i éin profil og velje tilfeldig blant dei, noko som fjernar skalet, kopien og skrivetilgangen heilt frå oppstartsbanen.
client
remote-random
<connection>
remote au1.example.net 1194 udp
</connection>
<connection>
remote au2.example.net 1194 udp
</connection>
Denne forma held tenarvalet inne i fila leverandøren skreiv, så ein rotasjon som gjev filer nye namn øydelegg ikkje uniten. Ho gjer også kandidatlista reviderbar, noko ein glob over ein katalog aldri er. Blandinga har framleis sin plass når profilar skil seg i meir enn eit endepunkt: ulike sertifikat, ulike rutingsdirektiv, ulik chifferpolitikk. I så fall er valet mellom heile konfigurasjonar, og eit skalsteg er den ærlege måten å uttrykkje det på.
Les attende instansen og fila han brukte
Stadfest kva unit som faktisk køyrer før du feilsøkjer innhaldet. Den pakka metetenesta og malen er infrastruktur; unitane som svarar til filene dine, er instansane som er oppkalla etter dei.
systemctl list-units 'openvpn*'
systemctl cat [email protected]
journalctl -u openvpn@au -n 30 --no-pager
Ein instans som ingen hugsar å ha slått på, fører vanlegvis attende til ei villfaren konfigurasjonsfil i pakkekatalogen. Slå av den namngjevne instansen i staden for malen, elles bringar neste pakkeoppgradering han tilbake. Etter endringa startar du uniten og les kommandolinja journalen rapporterer, og stadfestar deretter konfigurasjonsbanen han faktisk opna. Den eine kontrollen skil eit fungerande tilfeldig val frå ei teneste som stille brukar om att ei fil frå førre månad.