Naključna izbira OpenVPN v systemd: zakaj ExecStart odpove
systemd ni lupina, zato premešana kopija znotraj ExecStart umre. Premaknite izbiro v ExecStartPre ali pustite OpenVPN, da samo izbere strežnik.
Štirideset datotek .ovpn za eno državo prispe od ponudnika, in načrt se zdi očiten: kopirajte naključno na njeno mesto in nato zaženite tunel. Zapisano kot cevovod znotraj ExecStart, ta načrt umre ob zagonu s statusno kodo, ki ne pojasni ničesar. Datoteka enote ni skript, popravek pa je bodisi da eksplicitno vključite lupino bodisi da povsem prenehate izbirati datoteke.
Simptom: enota, ki se zažene in takoj umre
Stanje kaže, da je storitev spodletela v delčku sekunde, vrstica v dnevniku pa navaja ukaz, ki ga ne bi prejela nobena lupina. O tunelu se ne pokaže nič, ker se tunel ni nikoli začel.
Branje natančne ukazne vrstice iz dnevnika je najhitrejši način za potrditev tega. systemd ponovi, kar je izvedel, in niz bo prikazal znake cevovoda kot dobesedne argumente, ne kot operatorje.
Zakaj ExecStart ne more zagnati cevovoda
systemd sam razdeli ukazno vrstico, uporabi svoje narekovaje in zamenjavo spremenljivk ter nato rezultat izvede neposredno. Cevovodi, preusmerjanje, razširjanje vzorcev z lupino in zamenjava ukazov preprosto niso del te slovnice. To je oblikovalska odločitev in ne opustitev: enota deklarativno pove, kaj naj se izvede, logika lupine pa sodi v skript, ki ga enota pokliče. Oba popravka izhajata iz tega in noben ne zahteva, da enoti podelite več pravic.
To pojasni tudi zavajajočo izhodno kodo. Prvi argument se obravnava kot binarna datoteka, zato napačna vrstica spodleti, preden se izvede karkoli vaše logike.
Izbirajte v ExecStartPre
Neposredni popravek je pripravljalni korak, ki eksplicitno pokliče lupino in drži izbiro in zagon v isti enoti, da neuspeh v enem ne pusti drugega, da bi tekel sam.
[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
Tri podrobnosti odločajo, ali bo to preživelo srečanje z resničnim strojem. Poimenovanje je prva past: systemd zamenja %i že med razčlenjevanjem enote, veliko preden se zažene bash, zato mora specifikator stati zunaj enojnih narekovajev. xargs -r prepreči, da bi se cp zagnal brez argumenta, ko se vzorec ne ujema z ničimer. In neuspešen pripravljalni korak ustavi enoto, kar je pravilen izid: začeti z včerajšnjo konfiguracijo je slabše kot ne začeti. Naključna izbira, ki vedno vzame isto datoteko, običajno ni nesreča. Preverite, ali kopirano datoteko prepiše posodobitev paketa ali ali se vzorec ujema le z enim zastarelim vnosom.
Ali pustite OpenVPN, da izbere končno točko
OpenVPN že lahko hrani več končnih točk v enem profilu in med njimi naključno izbira, kar popolnoma odstrani lupino, kopiranje in pravico pisanja s poti zagona.
client
remote-random
<connection>
remote au1.example.net 1194 udp
</connection>
<connection>
remote au2.example.net 1194 udp
</connection>
Ta oblika drži izbiro strežnika v datoteki, ki jo je napisal ponudnik, zato rotacija, ki preimenuje datoteke, ne zlomi enote. Naredi tudi seznam kandidatov revizijsko sledljiv, česar vzorec nad imenikom nikoli ni. Mešanje si še vedno zasluži svoje mesto, ko se profili razlikujejo v več kot končni točki: drugačna potrdila, drugačne smerne direktive, drugačna politika šifriranja. V tem primeru je izbira med celotnimi konfiguracijami in korak z lupino je pošten način, da to izrazite.
Preberite nazaj primer in datoteko, ki jo je uporabil
Pred odpravljanjem napak v vsebini potrdite, katera enota res teče. Paketna meta storitev in predloga sta infrastruktura; enote, ki ustrezajo vašim datotekam, so primerki, poimenovani po njih.
systemctl list-units 'openvpn*'
systemctl cat [email protected]
journalctl -u openvpn@au -n 30 --no-pager
Primerek, za katerega se nihče ne spomni, da ga je omogočil, običajno vodi do zatavane konfiguracijske datoteke v imeniku paketa. Izklopite prav ta poimenovani primerek namesto predloge, sicer ga bo naslednja posodobitev paketa vrnila. Po spremembi zaženite enoto in preberite ukazno vrstico, ki jo poroča dnevnik, nato potrdite pot do konfiguracije, ki jo je res odprla. Ta ena preveritev loči delujočo naključno izbiro od storitve, ki tiho znova uporablja datoteko iz prejšnjega meseca.