OpenVPN veikia shell aplinkoje, bet nepavyksta po cron: kaltas PATH
Komanda, kuri prisijungia iš shell, gali nepavykti po cron ar subprocess dar prieš pradedant tunelį. Pataisykite kelią, darbinį katalogą ir terminalą.
Ta pati komanda prisijungia iš shell ir miršta po cron, tad natūrali išvada — kaltas tunelis arba sertifikatas. Prieš tuo patikėdami pažiūrėkite, ką abu paleidimai turi bendra: binariškasis failas, konfigūracija ir prisijungimo duomenys identiški, o pasikeitė tik proceso aplinka. Kai programa net nerandama, joks TLS derinimas nepadeda. Pataisymas dažniausiai glūdi kelyje, darbiniame kataloge ir saujoje aplinkos kintamųjų, o ne VPN.
command -v openvpn veikiančiame shell atspausdina atsakymą, ir tai labai dažnai /usr/sbin/openvpn, katalogas, kurio cron neįtraukia į savo paieškos kelią.
Tunelis niekada neprasidėjo, tad tunelis nėra problema
cron paleistos užduotys paveldi minimalią aplinką, paprastai PATH=/usr/bin:/bin, ir neturi valdančio terminalo. Viskas, kas įdiegta /usr/sbin ar /usr/local/sbin, tame sąraše tiesiog neegzistuoja, o žurnalo eilutė rodo openvpn: not found vietoj TLS klaidos. Python subprocess nepavyksta kitaip: jis paveldi interpretatoriaus proceso aplinką, kuri gali būti turtingesnė nei cron, bet vis tiek neturi shell, kuris išskleistų tildę. Abu nepavykimai įvyksta prieš vienam paketui paliekant mazgą.
Greitas būdas juos atskirti — skaityti pirmąją klaidą, o ne paskutinę. Trūkstamas binariškasis failas duoda shell arba Python išimtį, bloga konfigūracija duoda OpenVPN naudojimo pranešimą, o tikras rankos paspaudimo nepavykimas duoda laiko žymes ir partnerio adresus. Tik trečiasis yra tunelio problema.
Absoliutūs keliai ir argumentų sąrašai nugali shell eilutes
Perduokite išspręstą kelią aiškiai ir visiškai praleiskite shell. subprocess.run(["/usr/sbin/openvpn", "--config", config, "--verb", "4"], capture_output=True, text=True, timeout=90) duoda grąžinimo kodą, stdout ir stderr neprašant shell interpretuoti failo vardo. Konfigūracijos kelią kurkite iš os.environ["HOME"] arba pathlib.Path.home(), kad tildės niekada nereikėtų išskleisti. Kai tikrai reikia shell sintaksės, naudokite shlex.split, nes eilutės skaidymas su .split() lūžta bet kuriame kelyje su tarpu. Skaitykite ir stderr, nes OpenVPN ten rašo daugumą savo ankstyvų nepavykimų.
Ta pati taisyklė galioja ir cron: užduoties eilutė nėra prisijungimo shell, tad niekas neįkelia jūsų profilio ir niekas neapibrėžia jūsų slapyvardžių.
Ką crontab iš tikrųjų paveldi
crontab įrašas gauna tą aplinką, kurią deklaruoja crontab, plius keletą paveldėtų numatytųjų reikšmių, tad išrašykite kelią arba apvyniokite iškvietimą scenarijumi, kuris tai padaro. Eilutė kaip PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin failo viršuje apima įprastas diegimo vietas, o peradresavimas su >> cron.log 2>&1 yra tai, kas padaro kitą nepavykimą įskaitomą. Slaptažodžiu apsaugotas profilis po cron neturi būdo paprašyti savo paslapties, nes nėra terminalo, kuriame būtų galima paklausti. Tokia jungtis priklauso systemd įrenginiui, kuris gali skaityti prisijungimo duomenų failą, o ne užduočiai, kuri apsimeta interaktyvi.
Santykiniai keliai yra antroji spąstai. Bandomasis paleidimas dažnai vyksta iš aplanko, kuriame yra profilis, o cron užduotis prasideda visai kitur, tad --config office.ovpn išsprendžiamas į failą, kurio ten nėra, ir pranešimas skaitomas kaip trūkstamas failas, o ne trūkstamas tunelis.
Įrodykite tai nuimdami aplinką
Atkurkite minimalią aplinką tiesiogiai: env -i PATH=/usr/bin:/bin /usr/sbin/openvpn --config office.ovpn --verb 4. Skundas dėl kelio ar terminalo iš to paleidimo reiškia, kad problema yra aukščiau VPN. Jei prisijungia, likę įtariamieji yra paskyra, kuria jis veikia, katalogas, kuriame prasideda, ir prisijungimo duomuo, kurį pateikia. Bet kuris iš dviejų rezultatų geresnis už dar vieną sertifikatų tikrinimo ratą.
Tada padarykite apvalkalą pačiam save pranešantį. Išeikite su atskiru statusu kiekvienam pasiektam etapui, registruokite abu srautus su laiko žyme, ir kitas nepavykimas pasakys, ar jis mirė sprendžiant kelią, autentifikuojantis, ar po to, kai tunelis jau buvo pakeltas.
Įrenginiui taip pat reikia teisingos tvarkos: Wants=network-online.target kartu su After=network-online.target neleidžia klientui startuoti anksčiau, nei atsiranda adresas ar numatytasis maršrutas, kas kitaip pasireiškia kaip sertifikato ar TLS klaidos, kurios dingsta rankiniu būdu paleidus iš naujo.