Como definir a variável de ambiente no serviço systemd?

123

Eu tenho um sistema Arch Linux com systemd e criei meu próprio serviço. O serviço de configuração em /etc/systemd/system/myservice.service se parece com isto:

[Unit]
Description=My Daemon

[Service]
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

Agora quero definir uma variável de ambiente para o /bin/myforegroundcmd . Como eu faço isso?

    
por lfagundes 01.08.2012 / 21:43

5 respostas

149

Os horários mudam e as melhores práticas também.

A melhor maneira de fazer isso é executar systemctl edit myservice , o que criará um arquivo de substituição para você ou permitirá a edição de um já existente.

Em instalações normais, isso criará um diretório /etc/systemd/system/myservice.service.d e, dentro desse diretório, criará um arquivo cujo nome terminará em .conf (normalmente, override.conf ), e nesse arquivo você poderá adicionar ou substituir qualquer parte de a unidade enviada pela distribuição.

Por exemplo, em um arquivo /etc/systemd/system/myservice.service.d/myenv.conf :

[Service]
Environment="SECRET=pGNqduRFkB4K9C2vijOmUDa2kPtUhArN"
Environment="ANOTHER_SECRET=JP8YLOc2bsNlrGuD6LVTq7L36obpjzxd"

Observe também que, se o diretório existir e estiver vazio, seu serviço será desativado! Se você não pretende colocar algo no diretório, verifique se ele não existe.

Para referência, o jeito antigo era:

A maneira recomendada de fazer isso é criar um arquivo /etc/sysconfig/myservice que contenha seu variáveis e, em seguida, carregue-as com EnvironmentFile .

Para detalhes completos, veja a documentação do Fedora em como escrever um script systemd .

    
por 01.08.2012 / 22:07
68

A resposta depende se a variável deve ser constante (ou seja, não deve ser modificada pelo usuário que está obtendo a unidade) ou variável (supostamente definida pelo usuário).

Como é a sua unidade local, o limite é bastante desfocado e de qualquer forma funcionaria. No entanto, se você começar a distribuí-lo e acabar em /usr/lib/systemd/system , isso se tornará importante.

Valor constante

Se o valor não precisar ser alterado por instância, a maneira preferida seria colocá-lo como Environment= , diretamente no arquivo de unidade:

[Unit]
Description=My Daemon

[Service]
Environment="FOO=bar baz"
ExecStart=/bin/myforegroundcmd

[Install]
WantedBy=multi-user.target

A vantagem disso é que a variável é mantida em um único arquivo com a unidade. Portanto, o arquivo da unidade é mais fácil de se mover entre os sistemas.

Valor variável

No entanto, a solução acima não funciona bem quando o sysadmin deve alterar o valor da variável de ambiente localmente. Mais especificamente, o novo valor precisaria ser definido toda vez que o arquivo da unidade fosse atualizado.

Para este caso, um arquivo extra deve ser usado. Como - geralmente depende da política de distribuição.

Uma solução particularmente interessante é usar o diretório /etc/systemd/system/myservice.service.d . Ao contrário de outras soluções, esse diretório é suportado pelo próprio systemd e, portanto, não possui caminhos específicos de distribuição.

Nesse caso, você coloca um arquivo como /etc/systemd/system/myservice.service.d/local.conf , que adiciona as partes ausentes do arquivo de unidade:

[Service]
Environment="FOO=bar baz"

Em seguida, o systemd mescla os dois arquivos ao iniciar o serviço (lembre-se de systemctl daemon-reload depois de alterar qualquer um deles). E como esse caminho é usado diretamente pelo systemd, você não usa EnvironmentFile= para isso.

Se o valor deve ser alterado apenas em alguns dos sistemas afetados, você pode combinar as duas soluções, fornecendo um padrão diretamente na unidade e uma substituição local no outro arquivo.

    
por 23.04.2014 / 09:48
8

As respostas de Michael e Michał é útil e responde à pergunta original de como definir uma variável de ambiente para um serviço systemd. No entanto, um uso comum para variáveis de ambiente é configurar dados confidenciais, como senhas, em um local que não seja comprometido acidentalmente com o controle de origem com o código do seu aplicativo.

Se é por isso que você deseja transmitir uma variável de ambiente ao seu serviço, não use Environment= no arquivo de configuração da unidade. Use EnvironmentFile= e aponte para outro arquivo de configuração que só é legível pela conta de serviço (e usuários com acesso root).

Os detalhes do arquivo de configuração da unidade são visíveis para qualquer usuário com este comando:

systemctl show my_service

Eu coloquei um arquivo de configuração em /etc/my_service/my_service.conf e coloquei meus segredos lá:

MY_SECRET=correcthorsebatterystaple

Em seguida, no arquivo da unidade de serviço, usei EnvironmentFile= :

[Unit]
Description=my_service

[Service]
ExecStart=/usr/bin/python /path/to/my_service.py
EnvironmentFile=/etc/my_service/my_service.conf
User=myservice

[Install]
WantedBy=multi-user.target

Eu verifiquei que ps auxe não pode ver essas variáveis de ambiente e outros usuários não têm acesso a /proc/*/environ . Verifique no seu próprio sistema, é claro.

    
por 04.05.2018 / 02:29
6

Michael deu uma solução limpa, mas eu queria atualizar a variável env do script. Infelizmente, executar comandos bash não é possível no arquivo de unidade do systemd. Felizmente você pode acionar o bash dentro do ExecStart:

link

Note that this setting does not directly support shell command lines. If shell command lines are to be used they need to be passed explicitly to a shell implementation of some kind.

Exemplo no nosso caso é:

[Service]
ExecStart=/bin/bash -c "ENV='script'; /bin/myforegroundcmd"
    
por 23.07.2014 / 15:31