Isso $(ls -d...)
não funciona em um arquivo de unidade systemd:
[Service]
Type=forking
Environment="ORACLE_HOME=$(ls -d /usr/lib/oracle/*/client64 | sort -rV | head -n1)"
Environment="TNS_ADMIN=$(ls -d /usr/lib/oracle/*/client64/lib/network/admin | sort -rV | head -n1)"
Quero evitar codificar a versão do cliente Oracle (no momento 19.19), para simplificar as atualizações. Quando instalo um novo cliente Oracle, não quero modificar o arquivo da unidade systemd.
Como posso conseguir isso? Eu uso RHEL9 se isso for importante.
Métodos mais comuns:
Use um
EnvironmentFile=
que seja gerado dinamicamente, por exemplo, via ExecStartPre= que chama um script simples. As versões atuais do systemd relerão EnvironmentFile antes de cada execução para permitir que isso funcione. (/run é um bom local para o arquivo temporário.)Este é o método mais simples, pois o script só precisa escrever as
KEY="value"
linhas.Use um gerador systemd que grava dinamicamente arquivos de unidade em /run/systemd toda vez que a configuração é (re) carregada. O gerador pode ser um script de shell, desde que seja limitado ao acesso ao sistema de arquivos local.
Os geradores podem ser colocados
/etc/systemd/system-generators/
; eles serão executados durante cada inicialização e durante cada "systemctl daemon-reload", obtendo o caminho de saída como$1
. Eles funcionarão literalmente antes de qualquer unidade ser iniciada, portanto, não devem esperar que a rede ou qualquer outra coisa esteja ativa.Este é o método mais flexível, pois qualquer opção de unidade pode ser especificada dinamicamente – não apenas o ambiente, mas outras coisas como WorkingDirectory=. (O gerador não precisa criar uma unidade inteira ; ele pode ampliar as unidades existentes da maneira usual, criando
$1/oracle.service.d/environ.conf
ou similar.)Outros métodos:
Use uma unidade de serviço instanciada
[email protected]
que é usada%i
para preencher a versão. Você ainda precisará desabilitar "oracle@old" e habilitar "oracle@new", mas isso evita que você abra o editor de texto. (E também facilita a reversão rápida para a versão antiga apenas iniciando a unidade correta.) Acho que você pode ter umAlias=oracle.service
modo para que a ativação de uma instância a mapeie automaticamente para o nome mais curto.Use um script de shell wrapper que defina as variáveis e
exec
configure o programa real. Sim, oexec
é importante. (Além disso, use SyslogIdentifier= para evitar que o nome do script mostre a saída do journalctl.) Scripts wrapper geralmente são desencorajados, mas isso normalmente ocorre porque eles fazem coisas que podem ser feitas trivialmente a partir do .service, o que não é 100% o caso aqui.Evite
systemctl set-environment
porque é global – as variáveis ficarão disponíveis para todos os serviços iniciados a partir desse ponto, quer eles queiram ou não.