A mesma orde conéctase desde unha shell e morre baixo cron, así que a conclusión natural é que o túnel ou o certificado teñen a culpa. Mire que teñen en común as dúas execucións antes de crelo: o binario, a configuración e as credenciais son idénticos, e só cambiou a contorna do proceso. Cando o programa nin sequera se atopa, ningunha cantidade de depuración TLS axuda. A solución adoita estar nunha ruta, un directorio de traballo e un puñado de variables de contorna, non na VPN.

command -v openvpn na shell que funciona imprime a resposta, e moi a miúdo é /usr/sbin/openvpn, un directorio que cron non pon na súa ruta de busca.

O túnel nunca arrincou, así que o túnel non é o problema

Os traballos iniciados por cron herdan unha contorna mínima, convencionalmente PATH=/usr/bin:/bin, e ningún terminal de control. Todo o instalado en /usr/sbin ou /usr/local/sbin simplemente falta nesa lista, e a liña do rexistro di openvpn: not found en lugar dun erro de TLS. O subprocess de Python falla doutro xeito: herda a contorna do proceso do intérprete, que pode ser máis rica que a de cron pero aínda non ten ningunha shell que expanda un tilde. Ambos fallos ocorren antes de que un só paquete saia do servidor.

Unha forma rápida de distinguilos é ler o primeiro erro en lugar do último. Un binario que falta produce unha excepción de shell ou de Python, unha mala configuración produce unha mensaxe de uso de OpenVPN, e un fallo real de aperta de mans produce marcas de tempo e direccións de pares. Só o terceiro é un problema de túnel.

As rutas absolutas e as listas de argumentos gañan ás cadeas de shell

Pase a ruta resolvida explicitamente e salte a shell por completo. subprocess.run(["/usr/sbin/openvpn", "--config", config, "--verb", "4"], capture_output=True, text=True, timeout=90) dálle un código de retorno, stdout e stderr sen pedirlle a unha shell que interprete un nome de ficheiro. Constrúa a ruta da configuración a partir de os.environ["HOME"] ou pathlib.Path.home(), para que un tilde nunca teña que expandirse. Cando de verdade necesite sintaxe de shell, use shlex.split, porque dividir unha cadea con .split() rompe en calquera ruta que conteña un espazo. Lea tamén stderr, xa que OpenVPN escribe alí a maioría dos seus fallos temperáns.

A mesma regra vale para cron: a liña do traballo non é unha shell de inicio de sesión, así que nada carga o seu perfil e nada define os seus alias.

Que herda realmente un crontab

Unha entrada de crontab recibe a contorna que declara o crontab máis uns cantos valores por defecto herdados, así que escriba a ruta completa ou envolva a chamada nun script que o faga. Unha liña como PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin na parte superior do ficheiro cobre as localizacións de instalación habituais, e redirixir con >> cron.log 2>&1 é o que fai lexible o seguinte fallo. Un perfil protexido con contrasinal non ten forma de pedir o seu segredo baixo cron, xa que non existe un terminal onde preguntar. Esa conexión pertence a unha unidade de systemd que poida ler un ficheiro de credenciais, non a un traballo que finxe ser interactivo.

As rutas relativas son a segunda trampa. Unha proba adoita ocorrer desde o cartafol que contén o perfil, e un traballo de cron comeza noutro sitio por completo, así que --config office.ovpn resólvese nun ficheiro que non está e a mensaxe lese como un ficheiro que falta máis que como un túnel que falta.

Demóstroo despoxando a contorna

Reproduza a contorna mínima directamente: env -i PATH=/usr/bin:/bin /usr/sbin/openvpn --config office.ovpn --verb 4. Unha queixa de ruta ou de terminal desa execución significa que o problema está por riba da VPN. Se conecta, os sospeitosos restantes son a conta coa que se executa, o directorio no que arrinca e a credencial que presenta. Calquera dos dous resultados é mellor que outra rolda de comprobación de certificados.

Despois faga que o envoltorio se autoinforme. Saia cun estado distinto para cada etapa acadada, rexistre ambos fluxos cunha marca de tempo, e o seguinte fallo diralle se morreu na resolución da ruta, na autenticación ou despois de que o túnel xa estivese levantado.

Unha unidade tamén necesita unha orde correcta: Wants=network-online.target máis After=network-online.target impiden que o cliente arrinque antes de que exista unha dirección ou unha ruta por defecto, o que doutro xeito se manifesta como erros de certificado ou de TLS que desaparecen ao reiniciar a man.

Artigos relacionados