web-dev-qa-db-fra.com

Que signifie / bin / bash -c dans l'unité de service?

Pour que mon application s'exécute automatiquement lors du redémarrage.

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

Maintenant, mon application s'exécute automatiquement lors du redémarrage.
Je souhaite que mon application enregistre toutes les informations de sortie dans /var/log/app.log.
Voici ce que je fais.
1.Sudo touch /var/log/app.log
2. pour changer uniquement ExecStart.

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

L'application peut être exécutée mais aucun journal écrit dans /var/log/app.log.
Root exécutera l'application.
C'est la preuve ici.

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

Pourquoi root n’a-t-il pas l’autorisation d’écrire se connecter dans /var/log/app.log?

Pour changer l'instruction ExecStart en

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

Problème résolu.
1.Pourquoi la racine n’est-elle pas autorisée à écrire le journal dans /var/log/app.log?
2.Que signifie/bin/bash -c dans l'unité de service?

5

NOTE: L'ancienne publication a été écrite dans le contexte de la question initiale de OP, avant modifier, elle est donc incomplète, mais dans le contexte de ce qui a été demandé à l'origine, c'est toujours valide.

Réponse mise à jour:

La question clé ici est que

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

Shell ne fonctionne pas, donc votre redirection > et 2>&1 ne sera pas comprise par systemd.

C'est pourquoi Shell est nécessaire pour toute la commande afin que la redirection puisse fonctionner. En ce qui concerne le drapeau -c pour Shell, voir l’ancienne version du message ci-dessous.


OLD POST

Le drapeau -c dans bash et sh signifie la même chose: exécute les commandes comme indiqué dans les guillemets. Il n'y a pas de grand mystère.

Votre application que vous essayez d'exécuter peut avoir une signification différente pour l'option -c, ne présumez donc pas que tous les indicateurs de ligne de commande sont les mêmes pour toutes les commandes. Sans documentation pour l'application, il est difficile de dire ce qu'une option est censée faire.

Le problème potentiel ici est que l'interprète python considérera -c comme son propre argument de ligne de commande, pas avec l'application. C'est probablement la raison principale pour laquelle votre commande échoue.

Le ExecStart=/usr/bin/python /usr/local/bin/app -c /etc/app.json devrait pouvoir traiter votre commande. Je l'ai testé avec un petit 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

Meilleure approche: un script doit être rendu exécutable avec Sudo chmod +x /usr/local/bin/app et utilisé par lui-même. La façon dont il est écrit à l’origine, avec/bin/sh, puis python, puis l’appel du script réel est en quelque sorte redondant. Dans l'exemple de mon script de test, cela ressemblerait à ceci:

$ 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

Attention, python fait référence à Python 2.7 sur Ubuntu. Si vous devez utiliser spécifiquement Python3, utilisez plutôt/usr/bin/python3. Le moyen le plus préféré est que l'application ait #!/usr/bin/env python ou #!/usr/bin/env python3 en première ligne.

2

Ce n'est pas une question d'autorisations. Aucun shell n’est impliqué dans l’exécution de la chaîne ExecStart. Seule une commande et les options à transmettre à cette commande, mais ni les redirections, ni les canalisations, ni les encombrements avec ;, ni les substitutions, ni aucune autre fonctionnalité du shell. Ainsi, vos "redirections" sont transmises en tant qu'options à votre application (vous seul savez comment votre application gère cela).

Vous pouvez changer cela en appelant un shell et en donnant votre commande et vos redirections sous forme de chaîne de commande au shell. C’est ce que fait l’option -c.

Mais pensez à pourquoi ne pas utiliser les services et la journalisation comme prévu par systemd: Par défaut, stdout et stderr d’une unité systemd sont envoyés à syslog. Vous pouvez le configurer avec la ligne StandardOutput= dans votre service. Regardez man systemd.exec

3
Philippos

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 enable app.service

Pour rechercher le journal de l'application avec la commande journal.

Sudo journalctl  -u  app
1