OpenVPN funkcias en ŝelo sed malsukcesas sub cron: temas pri PATH
Komando, kiu konektiĝas el ŝelo, povas malsukcesi sub cron aŭ subprocess antaŭ ol la tunelo ekas. Riparu la vojon, la laboran dosierujon kaj la terminalon.
La sama komando konektiĝas el ŝelo kaj mortas sub cron, do la natura konkludo estas, ke la tunelo aŭ la atestilo kulpas. Rigardu, kion la du ruloj havas komunan antaŭ ol kredi tion: la dosiero, la agordo kaj la akreditaĵoj estas identaj, kaj nur la proceza medio ŝanĝiĝis. Kiam la programo eĉ ne troviĝas, nenia kvanto da TLS-sensxutado helpas. La riparo kutime troviĝas en vojo, labora dosierujo kaj plenmano da mediovariabloj, ne en la VPN.
command -v openvpn en la ŝelo, kiu funkcias, presas la respondon, kaj tre ofte ĝi estas /usr/sbin/openvpn, dosierujo, kiun cron ne metas en sian serĉovojon.
La tunelo neniam ekis, do la tunelo ne estas la problemo
Taskoj startigitaj de cron heredas minimuman medion, kutime PATH=/usr/bin:/bin, kaj neniun regan terminalon. Ĉio instalita en /usr/sbin aŭ /usr/local/sbin simple mankas en tiu listo, kaj la protokola linio diras openvpn: not found anstataŭ TLS-eraro. La subprocess de Python malsukcesas alie: ĝi heredas la medion de la interpretila procezo, kiu povas esti pli riĉa ol tiu de cron sed ankoraŭ havas neniun ŝelon por malvolvi tildon. Ambaŭ malsukcesoj okazas antaŭ ol unu sola pako forlasas la gastiganton.
Rapida maniero distingi ilin estas legi la unuan eraron anstataŭ la lastan. Mankanta dosiero produktas ŝelan aŭ Python-escepton, malbona agordo produktas uzan mesaĝon de OpenVPN, kaj vera manprema malsukceso produktas tempindikojn kaj samtavolajn adresojn. Nur la tria estas tunela problemo.
Absolutaj vojoj kaj argumentlistoj venkas ŝelajn ĉenojn
Transdonu la solvitan vojon eksplicite kaj tute preterlasu la ŝelon. subprocess.run(["/usr/sbin/openvpn", "--config", config, "--verb", "4"], capture_output=True, text=True, timeout=90) donas al vi revenan kodon, stdout kaj stderr sen peti ŝelon interpreti dosiernomon. Konstruu la agordan vojon el os.environ["HOME"] aŭ pathlib.Path.home(), por ke tilde neniam devu esti malvolvita. Kiam vi vere bezonas ŝelan sintakson, uzu shlex.split, ĉar disigo de ĉeno per .split() rompiĝas ĉe ĉiu vojo enhavanta spacon. Legu ankaŭ stderr, ĉar OpenVPN skribas tien plej multajn el siaj fruaj malsukcesoj.
La sama regulo validas por cron: la taska linio ne estas ensaluta ŝelo, do nenio ŝargas vian profilon kaj nenio difinas viajn alinomojn.
Kion crontab efektive heredas
crontab-ero ricevas tiun medion, kiun la crontab deklaras, plus kelkajn hereditajn defaŭltojn, do skribu la vojon plene aŭ envolvu la vokon en skripto, kiu tion faras. Linio kiel PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ĉe la supro de la dosiero kovras la kutimajn instalajn lokojn, kaj alidirektado per >> cron.log 2>&1 estas tio, kio faras la sekvan malsukceson legebla. Pasfrazo-protektita profilo havas neniun manieron peti sian sekreton sub cron, ĉar ne ekzistas terminalo por demandi. Tia konekto apartenas al systemd-unuo, kiu povas legi akreditan dosieron, ne al tasko, kiu ŝajnigas esti interaga.
Relativaj vojoj estas la dua kaptilo. Testa rulo ofte okazas el la dosierujo, kiu tenas la profilon, kaj cron-tasko startas tute aliloke, do --config office.ovpn solviĝas al dosiero, kiu ne tie estas, kaj la mesaĝo legeblas kiel mankanta dosiero prefere ol mankanta tunelo.
Pruvu tion senigante la medion
Reproduktu la minimuman medion rekte: env -i PATH=/usr/bin:/bin /usr/sbin/openvpn --config office.ovpn --verb 4. Plendo pri vojo aŭ terminalo el tiu rulo signifas, ke la problemo sidas super la VPN. Se ĝi konektiĝas, la restantaj suspektatoj estas la konto, sub kiu ĝi ruliĝas, la dosierujo, en kiu ĝi ekas, kaj la akreditaĵo, kiun ĝi prezentas. Ĉiu el la du rezultoj estas pli bona ol plia rondo de atestila kontrolado.
Poste faru la envolvilon memraportanta. Eliru kun aparta stato por ĉiu etapo, kiun ĝi atingis, protokolu ambaŭ fluojn kun tempindiko, kaj la sekva malsukceso diros al vi, ĉu ĝi mortis ĉe voj-solvado, ĉe aŭtentigo aŭ post kiam la tunelo jam estis supre.
Unuo ankaŭ bezonas ĝustan ordon: Wants=network-online.target plus After=network-online.target malhelpas al la kliento ekigi antaŭ ol ekzistas adreso aŭ defaŭlta vojo, kio alie montriĝas kiel atestilaj aŭ TLS-eraroj, kiuj malaperas ĉe mana restartigo.