Normalement, je ne poste pas ici, mais j'arrache mes cheveux par-dessus. J'ai un script Python qui bifurque lors de son lancement et est responsable du démarrage d'un tas d'autres processus. Ce script était lancé au démarrage via sysvinit, mais récemment j'ai mis à niveau vers Debian Jessie, je l'ai donc adapté pour être lancé via systemd.
Malheureusement, je rencontre un problème que je ne peux pas résoudre. Lorsque vous lancez le script directement dans un shell utilisateur, il lance correctement ses processus enfants et lorsque le script se termine, les processus enfants sont orphelins et continuent de s'exécuter.
Au lancement via systemd, si le processus parent se termine, les enfants sortent tous aussi (Eh bien, les écrans qu'ils lancent meurent et apparaissent comme morts ???)
Idéalement, je dois pouvoir redémarrer le script parent sans tuer tous les processus enfants, y a-t-il quelque chose qui me manque?
Merci!
[Unit]
Description=Server commander
After=network.target
[Service]
User=serveruser
Type=forking
PIDFile=/var/Server/Server.pid
ExecStart=/var/Server/Server.py
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
Edit: Il est probablement pertinent pour moi de souligner que le script Python est essentiellement un «contrôleur» pour ses processus enfants. Il démarre et arrête les serveurs dans les écrans GNU à la demande d'un serveur central. Il est normalement toujours en cours d'exécution, il ne génère pas de services et ne quitte pas. Il y a cependant des cas où j'aimerais pouvoir recharger le script sans tuer les processus enfants, même si cela signifie que les processus sont orphelins au pid 1. En fait, cela n'aurait même pas d'importance si le script Python a démarré les processus comme un processus parent, si cela est même possible.
Une meilleure explication de son fonctionnement:
- Systemd apparaît /Server.py
- Server.py fourche et écrit le fichier pid pour Systemd
- Server.py génère ensuite les processus serveur dans l'écran GNU en fonction de ses instructions
- Server.py continue de s'exécuter pour effectuer tous les redémarrages demandés au serveur
Lors du lancement sans Systemd, Server.py peut être redémarré et les écrans GNU qu'il lance ne sont pas affectés. Lors du lancement avec Systemd, lorsque Server.py s'arrête, au lieu que ces processus d'écran soient rendus orphelins au pid 1, ils sont tués.
la source
Server.py
code et une description de la façon dont les services lancés se bifurquent (s'ils se bifurquent). Cependant, d'une manière générale, il s'agit d'un problème de non-concordance du protocole de préparation .ExecStop=
n'est pas nécessaire. L'action par défaut de systemd à l'arrêt est de tuer les processus. Vous voudrez peut-être jeter un œil à la documentation deKillMode=
directive.simple
ouforking
, en fait), le dernier recours seraitType=oneshot
,RemainAfterExit=yes
etKillMode=control-group
.Réponses:
J'ai réussi à résoudre ce problème simplement en définissant KillMode sur process au lieu de control-group (par défaut). Merci a tous
la source
Ce qui indique que vous le faites mal. Plus à ce sujet dans un instant.
Ce n'est pas un comportement correct des démons. Si le processus "principal" - dans ce cas l'enfant que vous avez forké, puisque vous l'avez spécifié
Type=forking
- se termine, systemd considère que le service a été désactivé et met fin à tout autre processus encore en cours (dans le groupe de contrôle) afin de ranger .Parfois, la conversion des
rc
scripts System 5 en systemd n'est pas simple, car la bonne façon de faire les choses sous systemd est assez différente. La bonne façon de faire (disons) OpenVPN, ou OpenStack, ou OSSEC HIDS dans systemd n'est pas la même que l'on le ferait avec unrc
script. Le fait que vous ayez un script qui bifurque, puis génère toute une série de processus de petits-enfants, puis que vous vous attendez à ce que ces petits-enfants continuent de fonctionner indique que vous perpétrez le même type d'horreur queossec-control
, bien qu'avec deux niveaux de fourche de moins. Si vous vous retrouvez en train d'écrire un script "maître" qui vérifie les drapeaux "activer" et exécute des processus enfants pour les parties "activées" de votre système, alors vous faites la même erreur que l'horribleossec-control
.Aucun mécanisme de ce type n'est nécessaire avec systemd. C'est déjà un gestionnaire de services. Par /unix//a/200365/5132 , la bonne façon de procéder à ce sujet dans systemd n'est pas d'avoir un service qui engendre une tentative loufoque et confuse d'avoir des "sous-services". C'est d'avoir chaque processus enfant en tant que service système à part entière à part entière. Ensuite, on active et désactive, et démarre et arrête les différentes parties du système à l'aide des commandes systemd normales. Comme vous pouvez le voir dans le cas OSSEC HIDS, une unité de service de modèle simple couvre presque tous les services (à l'exception de /ubuntu//a/624871/43344 ), ce qui permet de faire des choses telles que l'
systemctl enable [email protected]
activation d'une optionagentlessd
sans aucun besoin de l’horrible mécanisme de "script maître" qui était nécessaire avec System 5rc
.Il existe de nombreux cas, peut-être pas aussi extrêmes que OSSEC HIDS, où une telle réflexion est nécessaire. Les MTS comme exim et sendmail en sont deux. On aurait pu avoir un seul
rc
script qui génère un exécuteur de file d'attente, un démon de soumission SMTP et un démon de relais SMTP, avec un tas de variables shell ad hoc dans un fichier de configuration pour contrôler exactement celles qui sont exécutées. Mais la bonne façon de le faire avec systemd est d'avoir trois unités de service appropriées (dont deux ont des unités de socket associées ) et pas de trucs ad hoc du tout, juste les mécanismes réguliers du gestionnaire de services.la source
Vous pouvez simplement dormir le parent et attendre que systemd le tue au moment de l'arrêt.
la source