ExecStart não é um shell: corrigir uma unidade auxiliar de VPN
ExecStart executa um programa com argumentos, não um pipeline de shell. Use um interpretador explícito ou um script real, depois verifique a unidade e leia o journal.
Copie uma linha de comando que funcione para o ExecStart, recarregue, e a unidade falha ou termina em silêncio, tratando os argumentos como nomes de ficheiro. Nada está quebrado no systemd. ExecStart é uma lista de argumentos, não um shell, por isso pipes, redirecionamento e condições perdem o sentido no momento em que saem do seu terminal. Decida onde o shell deve ficar e depois escreva uma unidade que diga exatamente o que deve ser executado.
Por que o pipeline no ExecStart não faz nada
Quando um comando é digitado num terminal, o shell analisa-o primeiro. Constrói um pipeline, abre ficheiros para redirecionamento e expande variáveis antes de qualquer programa começar. O systemd não faz nada disso: divide o ExecStart segundo as suas próprias regras e executa o programa resultante com esses argumentos. Por isso > chega como argumento literal, e um | é entregue ao programa em vez de ligar dois processos. A unidade não se comporta mal; a sintaxe queria dizer outra coisa.
Isso é deliberado e não descuidado, porque o tratamento previsível dos argumentos é o que torna as unidades auditáveis. Só surpreende quem assume que existe um shell.
Escreva uma unidade que diga exatamente o que corre
Comece com uma unidade pequena cujo propósito seja visível no journal, para que os problemas de análise fiquem separados dos problemas do túnel. Esta apenas reporta a versão de um binário.
[Unit]
Description=Report the installed OpenVPN version
[Service]
Type=oneshot
ExecStart=/usr/sbin/openvpn --version
StandardOutput=journal
StandardError=journalO caminho é um marcador de posição, por isso substitua-o pelo binário que está realmente instalado. Type=oneshot adequa-se a um comando que corre até ao fim, e as definições do journal colocam a sua saída onde a pode ler sem terminal. Deliberadamente não há secção de instalação, por isso a unidade é invocada à mão em vez de ser ativada no arranque. Valide o ficheiro antes de o iniciar, porque um erro de escrita no nome de uma diretiva falha de forma diferente de um erro no caminho.
systemd-analyze verify /etc/systemd/system/openvpn-version.service
systemctl start openvpn-version.serviceMantenha a lógica de shell num script
Quando um auxiliar precisa mesmo de lógica condicional, coloque essa lógica num script e chame-o explicitamente. O script precisa de uma linha de interpretador, permissão de execução e códigos de saída que o serviço possa reportar. Lançar /bin/sh -c com um comando entre aspas funciona, mas esconde as regras de aspas dentro de uma unidade e dificulta a revisão. Um script com nome pode ser testado à mão e substituído mais tarde sem editar a unidade. Não dependa do perfil de shell do utilizador interativo, porque um serviço arranca com o seu próprio ambiente.
Defina WorkingDirectory quando os caminhos relativos importam, e passe o ambiente através das diretivas suportadas da unidade em vez de o exportar num terminal. Os segredos pertencem a ficheiros protegidos ou credenciais, não a listas de argumentos que o journal possa registar.
Verifique a unidade que realmente existe
Os ficheiros drop-in mudam o comportamento sem tocar no ficheiro que se lembra de ter editado. Leia o que o gestor carregou e o que a última execução reportou.
systemctl cat vpn-helper.service
journalctl -u vpn-helper.service -n 20 --no-pagerO dump da unidade inclui os ficheiros drop-in por ordem de carregamento, e é daí que normalmente vem um ExecStart inesperado. Após qualquer alteração, recarregue o gestor e confirme que a nova definição é o que imprime systemctl cat. O journal mostra a linha de comando exata e o estado de saída, o que separa um problema de argumentos de um binário em falta ou de um erro de permissões. Depois decida se o auxiliar pertence ao ciclo de vida da VPN existente ou deve continuar a ser um diagnóstico manual, porque um segundo processo de túnel em segundo plano cria um proprietário concorrente.
Uma unidade que imprime a saída certa a pedido é um bom primeiro marco. Ainda não é um túnel, e não deve fingir que é.