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?
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.
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.
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
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