Véletlenszerű OpenVPN-választás a systemd-ben: miért vall kudarcot az ExecStart
A systemd nem shell, ezért az ExecStart belsejében megkevert másolat elhal. Vigye a választást az ExecStartPre alá, vagy hagyja, hogy az OpenVPN maga válasszon szervert.
Negyven .ovpn fájl érkezik egy országhoz egy szolgáltatótól, és a terv kézenfekvőnek tűnik: másolj be egy véletlenszerűt a helyére, majd indítsd el az alagutat. Az ExecStart belsejében csővezetékként megírva ez a terv már indításkor elhal egy olyan állapotkóddal, amely semmit sem magyaráz. Az unit fájl nem szkript, és a javítás vagy az, hogy kifejezetten behozunk egy shellt, vagy az, hogy teljesen abbahagyjuk a fájlok választását.
A tünet: egy unit, amely elindul és azonnal elhal
Az állapot azt mutatja, hogy a szolgáltatás a másodperc töredéke alatt meghiúsult, és a naplósor olyan parancsot nevez meg, amelyet egyetlen shell sem kapott volna meg soha. Az alagútról semmi sem jelenik meg, mert az alagút soha nem kezdődött el.
A pontos parancssor kiolvasása a naplóból a leggyorsabb módja ennek megerősítésére. A systemd visszaadja, amit végrehajtott, és a karakterlánc a csővezeték karaktereit szó szerinti argumentumként fogja mutatni, nem operátorokként.
Miért nem tud az ExecStart csővezetéket futtatni
A systemd maga bontja fel a parancssort, saját idézőjelezését és változóhelyettesítését alkalmazza, majd az eredményt közvetlenül végrehajtja. A csövek, az átirányítás, a shell általi glob-kiterjesztés és a parancshelyettesítés egyszerűen nem részei ennek a nyelvtannak. Ez tervezési döntés, nem mulasztás: az unit deklaratívan megmondja, mit kell futtatni, a shell-logika pedig abba a szkriptbe tartozik, amelyet az unit meghív. Mindkét javítás ebből következik, és egyik sem igényli, hogy az unit több jogosultságot kapjon.
Ez magyarázza a félrevezető kilépési kódot is. Az első argumentumot binárisként kezeli, ezért egy hibás sor már a logikád bármely részének futása előtt meghiúsul.
A választást az ExecStartPre-ben végezd el
A közvetlen javítás egy előkészítő lépés, amely kifejezetten meghív egy shellt, és a választást meg az indítást ugyanabban az unitban tartja, hogy az egyik hibája ne hagyja a másikat egyedül futni.
[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
Három részlet dönti el, hogy ez kibírja-e egy valódi géppel való találkozást. A névadás az első csapda: a systemd már az unit elemzésekor helyettesíti a %i-t, jóval azelőtt, hogy a bash futna, ezért a specifikátornak egyszeres idézőjeleken kívül kell állnia. A xargs -r megakadályozza, hogy a cp argumentum nélkül fusson, amikor a glob semmire sem illeszkedik. Egy meghiúsult előkészítő lépés pedig leállítja az unitot, és ez a helyes eredmény: a tegnapi konfigurációval elindulni rosszabb, mint el sem indulni. Az a véletlenszerű választás, amely mindig ugyanazt a fájlt veszi, általában nem balszerencse. Ellenőrizd, hogy a másolt fájlt felülírja-e egy csomagfrissítés, vagy hogy a glob csak egyetlen elavult bejegyzésre illeszkedik.
Vagy hagyd, hogy az OpenVPN válassza ki a végpontot
OpenVPN már tud több végpontot tartani egy profilban, és véletlenszerűen választani közülük, ami teljesen kiveszi a shellt, a másolást és az írási hozzáférést az indítási útvonalból.
client
remote-random
<connection>
remote au1.example.net 1194 udp
</connection>
<connection>
remote au2.example.net 1194 udp
</connection>
Ez a forma a szerverválasztást a szolgáltató által írt fájlon belül tartja, így a fájlokat átnevező rotáció nem töri el az unitot. A jelöltlistát is ellenőrizhetővé teszi, ami egy könyvtár feletti glob soha nem. A keverés még mindig megérdemli a helyét, amikor a profilok többben különböznek egy végpontnál: más tanúsítványok, más útválasztási direktívák, más titkosítási szabályzat. Ebben az esetben a választás egész konfigurációk között van, és egy shell-lépés az őszinte módja ennek kifejezésére.
Olvasd vissza a példányt és a fájlt, amelyet használt
Erősítsd meg, melyik unit fut valójában, mielőtt hibakeresnéd a tartalmát. A csomagolt meta-szolgáltatás és a sablon infrastruktúra; a fájljaidnak megfelelő unitok azok a példányok, amelyek róluk kapták a nevüket.
systemctl list-units 'openvpn*'
systemctl cat [email protected]
journalctl -u openvpn@au -n 30 --no-pager
Egy példány, amelyről senki sem emlékszik, hogy engedélyezte, általában egy elkóborolt konfigurációs fájlhoz vezet a csomagkönyvtárban. Kapcsold ki azt a megnevezett példányt a sablon helyett, különben a következő csomagfrissítés visszahozza. A változtatás után indítsd el az unitot, és olvasd ki a napló által jelentett parancssort, majd erősítsd meg a konfigurációs útvonalat, amelyet valóban megnyitott. Ez az egyetlen ellenőrzés választja el a működő véletlenszerű választást attól a szolgáltatástól, amely csendben újrahasznál egy múlt havi fájlt.