O que significa / bin / bash -c significa na unidade de serviço?

5

Para autorizar a execução do meu aplicativo durante a reinicialização.

sudo vi /etc/systemd/system/app.service

[Unit]
Description=app
After=network.target

[Service]
ExecStart=/usr/bin/python /usr/local/bin/app  
[Install]
WantedBy=multi-user.target


sudo systemctl daemon-reload
sudo systemctl enable app.service

Agora meu aplicativo é executado automaticamente durante a reinicialização.
Eu quero fazer meu aplicativo escrever todas as informações de saída em /var/log/app.log.
Aqui está o que eu faço.
1.sudo toque /var/log/app.log
2. para alterar somente o ExecStart.

ExecStart=/usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1

O aplicativo pode ser executado, mas nenhum log gravado em /var/log/app.log.
Raiz irá executar o aplicativo.
É prova aqui.

ps aux|grep  app
root       246  0.0  3.8  56052 10056 ?        Ss   00:57   0:00 /usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1

Por que o root não tem permissão para gravar o log em /var/log/app.log?

Para alterar a instrução ExecStart para

ExecStart=/bin/sh -c '/usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1'  

Problema resolvido.
1.por que root não tem permissão para gravar log em /var/log/app.log?
2. O que significa / bin / bash -c significa na unidade de serviço?

    
por it_is_a_literature 04.05.2017 / 04:34

3 respostas

2

OBSERVAÇÃO : O post antigo foi escrito no contexto da pergunta original do OP, antes de edição, por isso está incompleto, mas no contexto do que foi originalmente perguntado, ainda é válido.

Resposta atualizada:

A questão chave aqui é que

ExecStart=/usr/bin/python /usr/local/bin/app   > /var/log/app.log 2>&1

Não tem o shell em execução, portanto, o redirecionamento > e 2>&1 não será compreendido pelo systemd.

É por isso que o shell é necessário em todo o comando para que o redirecionamento possa funcionar. Quanto a -c flag para shell, veja a versão antiga do post abaixo.

OLD POST

O sinal -c em bash e sh significa a mesma coisa: execute os comandos conforme fornecidos nas cotas. Não há grande mistério.

Seu aplicativo que você está tentando executar pode ter um significado diferente para o sinalizador -c, portanto, não presuma que todos os sinalizadores de linha de comando são os mesmos para todos os comandos. Sem documentação para o aplicativo, é difícil dizer o que uma opção deve fazer.

Problema potencial aqui é que o interpretador python assumirá -c como seu próprio argumento de linha de comando, não para o aplicativo. Provavelmente, essa é a principal razão pela qual seu comando falha.

O ExecStart=/usr/bin/python /usr/local/bin/app -c /etc/app.json deve ser capaz de processar seu comando. Eu testei com um pequeno script:

$ cat test_script.py
import sys
print sys.argv[1],sys.argv[0]
$ python test_script.py this is a test                
this test_script.py

Melhor abordagem: um script deve ser executado com sudo chmod +x /usr/local/bin/app e usado sozinho. O modo como é escrito originalmente, com / bin / sh, e depois python, chamando o script real é meio redundante. No exemplo do meu script de teste, seria assim:

$ cat test_script.py                                  
#!/usr/bin/env python
import sys
print sys.argv[1],sys.argv[0]
$ chmod +x test_script.py
$ ./test_script.py this is a test
this ./test_script.py

Tenha em atenção que python refere-se ao Python 2.7 no Ubuntu. Se você precisar usar especificamente o Python3, use / usr / bin / python3. A maneira mais preferida é que o aplicativo tenha #!/usr/bin/env python ou #!/usr/bin/env python3 como primeira linha.

    
por Sergiy Kolodyazhnyy 04.05.2017 / 04:43
3

Não é uma questão de permissões. Simplesmente não há shell envolvido na execução da string ExecStart . Apenas um comando e as opções a serem passadas para esse comando, mas nenhum redirecionamento nem canalização nem concatenação com ; nem substituição ou qualquer outra funcionalidade do shell. Assim, seus "redirecionamentos" são passados como opções para seu aplicativo (somente você sabe como seu aplicativo lida com isso).

Você pode alterar isso chamando um shell e fornecendo seu comando e redirecionamentos como uma cadeia de comandos para o shell. Isso é o que a opção -c faz.

Mas pense em por que não usar os serviços e o log como pretendido pelo systemd: Por padrão, stdout e stderr de uma unidade systemd são enviados para o syslog. Você pode configurá-lo com a linha StandardOutput= em seu serviço. Dê uma olhada em man systemd.exec

    
por Philippos 04.05.2017 / 07:59
1

sudo vi /etc/systemd/system/app.service

[Unit]
Description=app
After=network.target

[Service]
ExecStart=/usr/bin/python /usr/local/bin/app  
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
sudo systemctl ativar app.service

Para pesquisar o log do aplicativo com o comando journal.

sudo journalctl  -u  app
    
por it_is_a_literature 04.05.2017 / 09:43