OpenVPN kjører i et skall, men feiler under cron: det er PATH
En kommando som kobler til fra et skall, kan feile under cron eller subprocess før tunnelen starter. Rett opp stien, arbeidsmappen og terminalen.
Den samme kommandoen kobler til fra et skall og dør under cron, så den naturlige konklusjonen er at tunnelen eller sertifikatet er skyld i det. Se på hva de to kjøringene har felles før du tror på det: binæren, konfigurasjonen og påloggingsinformasjonen er identiske, og bare prosessmiljøet er endret. Når programmet ikke engang blir funnet, hjelper ingen mengde TLS-feilsøking. Rettelsen ligger vanligvis i en sti, en arbeidsmappe og en håndfull miljøvariabler, ikke i VPN-en.
command -v openvpn i skallet som virker skriver ut svaret, og det er svært ofte /usr/sbin/openvpn, en mappe som cron ikke setter på søkestien sin.
Tunnelen startet aldri, så tunnelen er ikke problemet
Jobber som startes av cron, arver et minimalt miljø, vanligvis PATH=/usr/bin:/bin, og ingen kontrollerende terminal. Alt som er installert i /usr/sbin eller /usr/local/sbin mangler rett og slett på den listen, og logglinjen sier openvpn: not found i stedet for en TLS-feil. Pythons subprocess feiler annerledes: den arver miljøet til tolkerprosessen, som kan være rikere enn cron sitt, men fortsatt ikke har noe skall til å utvide en tilde. Begge feilene skjer før én eneste pakke forlater verten.
En rask måte å skille dem på er å lese den første feilen i stedet for den siste. En manglende binær gir en skall- eller Python-unntakelse, en dårlig konfigurasjon gir en OpenVPN-bruksmelding, og en ekte håndtrykkfeil gir tidsstempler og peer-adresser. Bare den tredje er et tunnelproblem.
Absolutte stier og argumentlister slår skallstrenger
Send den oppløste stien eksplisitt og hopp over skallet helt. subprocess.run(["/usr/sbin/openvpn", "--config", config, "--verb", "4"], capture_output=True, text=True, timeout=90) gir deg returkode, stdout og stderr uten å be et skall tolke et filnavn. Bygg konfigurasjonsstien fra os.environ["HOME"] eller pathlib.Path.home(), slik at en tilde aldri må utvides. Når du virkelig trenger skallsyntaks, bruk shlex.split, fordi å dele en streng med .split() bryter på enhver sti som inneholder et mellomrom. Les også stderr, siden OpenVPN skriver de fleste av sine tidlige feil der.
Den samme regelen gjelder cron: jobblinjen er ikke et innloggingsskall, så ingenting laster profilen din, og ingenting definerer aliasene dine.
Hva en crontab faktisk arver
En crontab-oppføring får miljøet crontab-en erklærer, pluss noen få arvede standardverdier, så skriv ut stien eller pakk kallet inn i et skript som gjør det. En linje som PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin øverst i filen dekker de vanlige installasjonsstedene, og omdirigering med >> cron.log 2>&1 er det som gjør den neste feilen lesbar. En passfrasebeskyttet profil har ingen måte å be om hemmeligheten sin under cron, siden det ikke finnes noen terminal å spørre på. En slik tilkobling hører hjemme i en systemd-enhet som kan lese en påloggingsfil, ikke i en jobb som later som den er interaktiv.
Relative stier er den andre fellen. En testkjøring skjer ofte fra mappen som inneholder profilen, og en cron-jobb starter helt andre steder, så --config office.ovpn peker på en fil som ikke er der, og meldingen leses som en manglende fil snarere enn en manglende tunnel.
Bevis det ved å skrelle av miljøet
Gjenskap det minimale miljøet direkte: env -i PATH=/usr/bin:/bin /usr/sbin/openvpn --config office.ovpn --verb 4. En klage på sti eller terminal fra den kjøringen betyr at problemet sitter over VPN-en. Hvis den kobler til, er de gjenværende mistenkte kontoen den kjører som, mappen den starter i, og påloggingsinformasjonen den legger fram. Begge resultatene er bedre enn enda en runde med sertifikatkontroll.
Gjør deretter innpakningen selvrapporterende. Avslutt med en egen status for hvert trinn den nådde, logg begge strømmene med tidsstempel, og den neste feilen forteller deg om den døde ved stioppslag, ved autentisering eller etter at tunnelen allerede var oppe.
En enhet trenger også riktig rekkefølge: Wants=network-online.target pluss After=network-online.target hindrer klienten i å starte før en adresse eller standardrute finnes, noe som ellers viser seg som sertifikat- eller TLS-feil som forsvinner ved en manuell omstart.