OpenVPN teče v lupini, a pod cronom odpove: kriv je PATH
Ukaz, ki se poveže iz lupine, lahko pod cronom ali subprocessom odpove, še preden se tunel zažene. Popravite pot, delovno mapo in terminal.
Isti ukaz se poveže iz lupine in pod cronom umre, zato je naravni sklep, da sta kriva tunel ali potrdilo. Preden temu verjamete, poglejte, kaj imata oba zagona skupnega: binarna datoteka, konfiguracija in poverilnice so enake, spremenilo se je le okolje procesa. Ko programa niti ne najdejo, nobeno razhroščevanje TLS ne pomaga. Popravek običajno tiči v poti, delovni mapi in peščici okoljskih spremenljivk, ne v VPN.
command -v openvpn v lupini, ki deluje, izpiše odgovor, in to je zelo pogosto /usr/sbin/openvpn, mapa, ki je cron ne doda na svojo iskalno pot.
Tunel se ni nikoli zagnal, zato tunel ni problem
Opravila, ki jih zažene cron, podedujejo minimalno okolje, običajno PATH=/usr/bin:/bin, in brez krmilnega terminala. Vse, kar je nameščeno v /usr/sbin ali /usr/local/sbin, v tem seznamu preprosto manjka, in vrstica v dnevniku pravi openvpn: not found namesto napake TLS. Pythonov subprocess odpove drugače: podeduje okolje procesa tolmača, ki je lahko bogatejše od cronovega, a še vedno nima lupine, ki bi razširila tildo. Obe napaki se zgodita, preden en sam paket zapusti gostitelja.
Hiter način, da ju ločite, je branje prve napake namesto zadnje. Manjkajoča binarna datoteka ustvari izjemo lupine ali Pythona, slaba konfiguracija ustvari sporočilo o uporabi OpenVPN, resnična napaka rokovanja pa ustvari časovne žige in naslove partnerjev. Samo tretja je težava tunela.
Absolutne poti in seznami argumentov premagajo lupinske nize
Posredujte razrešeno pot izrecno in lupino popolnoma preskočite. subprocess.run(["/usr/sbin/openvpn", "--config", config, "--verb", "4"], capture_output=True, text=True, timeout=90) vam da povratno kodo, stdout in stderr, ne da bi lupino prosili za razlago imena datoteke. Pot do konfiguracije zgradite iz os.environ["HOME"] ali pathlib.Path.home(), da tilde nikoli ne bo treba razširiti. Ko resnično potrebujete lupinsko sintakso, uporabite shlex.split, ker se deljenje niza z .split() zlomi na vsaki poti s presledkom. Berite tudi stderr, saj OpenVPN tja zapiše večino svojih zgodnjih odpovedi.
Isto pravilo velja za cron: vrstica opravila ni prijavna lupina, zato nič ne naloži vašega profila in nič ne definira vaših aliasov.
Kaj crontab v resnici podeduje
Vnos v crontabu dobi okolje, ki ga crontab navede, plus nekaj podedovanih privzetih vrednosti, zato pot izpišite ali klic zavijte v skript, ki to naredi. Vrstica, kot je PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin na vrhu datoteke, pokrije običajne namestitvene lokacije, in preusmeritev z >> cron.log 2>&1 je tisto, kar naredi naslednjo odpoved berljivo. Profil, zaščiten s geslom, pod cronom ne more vprašati za svojo skrivnost, ker ni terminala, na katerem bi vprašal. Takšna povezava sodi v enoto systemd, ki zna brati datoteko s poverilnicami, ne v opravilo, ki se pretvarja, da je interaktivno.
Relativne poti so druga past. Preizkusni zagon se pogosto zgodi iz mape s profilom, opravilo cron pa se začne povsem drugje, zato se --config office.ovpn razreši v datoteko, ki je tam ni, in sporočilo se bere kot manjkajoča datoteka, ne manjkajoč tunel.
Dokažite to tako, da slečete okolje
Ponovno ustvarite minimalno okolje neposredno: env -i PATH=/usr/bin:/bin /usr/sbin/openvpn --config office.ovpn --verb 4. Pritožba glede poti ali terminala iz tega zagona pomeni, da težava sedi nad VPN. Če se poveže, so preostali osumljenci račun, pod katerim teče, mapa, v kateri se začne, in poverilnica, ki jo predloži. Kateri koli od obeh izidov je boljši od še enega kroga preverjanja potrdil.
Nato naredite ovoj samoporočajoč. Končajte z ločenim stanjem za vsako doseženo stopnjo, zabeležite oba toka s časovnim žigom, in naslednja odpoved vam bo povedala, ali je umrl pri razreševanju poti, pri preverjanju pristnosti ali potem, ko je tunel že stal.
Enota potrebuje tudi pravilen vrstni red: Wants=network-online.target skupaj s After=network-online.target preprečita, da bi se odjemalec zagnal, preden obstaja naslov ali privzeta pot, kar se sicer pokaže kot napake potrdila ali TLS, ki izginejo ob ročnem ponovnem zagonu.