Forum Linux.général systemd et ordre de démarrage

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
5
jan.
2018

Bonjour,

Sur un raspberrypi sous raspbian je rencontre un problème d'ordre de démarrage.
J'ai un service perso qui utilise influxdb ainsi qu'un autre service perso. Il doit donc démarrer après ceux-ci. J'ai ajouté dans la section [unit]:

Requires=local-fs.target gpio_init.service influxdb.service
After=gpio_init.service influxdb.service

Après j'ai fait un systemctl daemon-reload

Mais malgré cela mon service démarre avant qu'influxdb ait finit de démarrer.

Auriez-vous une idée de pourquoi et comment faire pour que les dépendances se fassent bien ?

  • # Bogue connu ?

    Posté par  (site web personnel) . Évalué à 4.

    Les métadonnées citées me semblent plutôt correctes. En cherchant « systemd wait until a unit is ready », des fois qu'il y a des choses particulières à savoir qui ne seraient pas documentées dans man:systemd.unit, je suis tombé sur un rapport de bogue influx. ;)

    Debian Consultant @ DEBAMAX

    • [^] # Re: Bogue connu ?

      Posté par  . Évalué à -1.

      mmh, je vois que c'est toujours un peu la misère avec systemd que init, :)

      promesse non tenu

    • [^] # Re: Bogue connu ?

      Posté par  . Évalué à 2.

      Merci pour les liens ça semble intéressant effectivement.

  • # pid vs healthcheck

    Posté par  . Évalué à 3.

    Je suis un peu confronté au même problème, avec SysV Init, j'était capable d'attendre qu'un service soit disponible (via un healthcheck) pour démarrer le suivant, avec SystemD, je n'ai pas trouvé comment faire, de ce que j'ai compris, SystemD considère qu'un service est UP à partir du moment ou le PID est présent, ce qui ne veut pas forcement dire qu'il est disponible.
    J'ai trouvé un workaround dégueulasse et posant un délai avant le démarrage du second service…

    • [^] # Re: pid vs healthcheck

      Posté par  (site web personnel) . Évalué à 5.

      Ça reste un problème classique d'adminsys non ? Mon service marche-t-il quand le processus est lancé, quand le port est ouvert, quand le processus est capable de répondre à une requête sur le port concerné, quand le processus est capable de répondre correctement à une requête sur le port concerné ? Etc.

      Détaillons avec un exemple, disons Elasticsearch (simplifions en disant que c'est un applicatif Java qui répond à des requêtes web) :

      • machine virtuelle Java (JVM) non lancée -> pas de processus
      • JVM lancée, mais l'applicatif pas vraiment -> processus, pas encore le port TCP 9200 ouvert mais ça ne va pas tarder
      • JVM lancée, applicatif en cours de lancement -> port ouvert, mais une requête va échouer, avec une réponse du type « pas encore dispo »
      • tout est lancé -> une requête de test de vie aura une réponse HTTP 200 OK

      Bon ça c'était le cas « simple ». Prenons maintenant une grappe de serveurs Elasticsearch… Alors ma grappe est-elle fonctionnelle ? Les données sont-elles accessibles ? Etc.

      Pour détailler : sur un serveur donné, j'ai bien lancé la JVM, l'applicatif a démarré, tout semble OK. Mais il faut par exemple deux serveurs maître au minimum (min_masters) pour que ça marche. Du coup mon serveur ne va pas encore répondre à mes requêtes ou bien répondre en erreur (« serveurs maîtres indisponibles »). Ou bien encore il faut que tel serveur de données soit là, parce que c'est lui qui héberge réellement les données, et alors l'ensemble de ma grappe n'est pas fonctionnelle (au sens il me manque des données) et une réponse sur mon serveur initial sera en erreur ou partielle.

      Bref définir ce que veut dire « avoir bien démarré » n'est pas forcément trivial, et c'est pourtant une question classique.

      • [^] # Re: pid vs healthcheck

        Posté par  (site web personnel) . Évalué à 5. Dernière modification le 06 janvier 2018 à 17:02.

        Sinon systemd permet Type=notify pour permettre lui signaler que l'initialisation est complète (par exemple /lib/systemd/system/systemd-journald.service et /lib/systemd/system/systemd-udevd.service ). (mais ça ne résout pas la question de savoir ce que initialisation complète veut dire, pour le système, pour le fonctionnel ou pour l'utilisateur)

  • # Type de service

    Posté par  . Évalué à 2.

    Quel test, quelle condition, permet d'affirmer que « À présent, influxdb a fini de démarrer, et les services qui dépendent d'influxdb peuvent maintenant être lancés » ?

    influxdb est un service de quel Type ? Il me semble que cette option a un rôle à jouer.

    Peux-tu poster le contenu du fichier influxdb.service ?

    • [^] # Re: Type de service

      Posté par  . Évalué à 1. Dernière modification le 06 janvier 2018 à 16:08.

      Voici ce qu'il y a dans /etc/systemd/system/influxd.service :

      # If you modify this, please also make sure to edit init.sh
      
      [Unit]
      Description=InfluxDB is an open-source, distributed, time series database
      Documentation=https://docs.influxdata.com/influxdb/
      After=network-online.target
      
      [Service]
      User=influxdb
      Group=influxdb
      LimitNOFILE=65536
      EnvironmentFile=-/etc/default/influxdb
      ExecStart=/usr/bin/influxd -config /etc/influxdb/influxdb.conf $INFLUXD_OPTS
      KillMode=control-group
      Restart=on-failure
      
      [Install]
      WantedBy=multi-user.target
      Alias=influxd.service
      
      • [^] # Re: Type de service

        Posté par  . Évalué à 7.

        (astuce: si tu utilise systemctl cat influxd.service il t'affichera non seulement le fichier de base, où qu'il se trouve, mais aussi d'éventuels fragments supplémentaires qu'il aurait inclus en plus)

        Le type de service n'est pas précisé (et il n'y a pas de BusName), donc il est implicitement de type simple. Ça veut dire que dès que le programme indiqué par ExecStart est lancé le service est considér(é comme démarré. Mais je suppose que ton service influxd met un certain tempos à être fonctionnel.
        La documentation de systemd recommande dans ce cas de mettre en place le socket à l'avance via systemd (qui lui bloquera en attendant que le service répond correctement), mais ça suppose d'être supporté par ton service (ce qui n'est probablement pas le cas), ou d'utiliser un proxy (plus tordu et peut-être moins bon pour les performances).

        Sinon, dans ton propre service, tu peux ajouter un ExecStartPre qui va exécuter un script qui va attendre que le service soit correctement démarré (le programme défini en ExecStart n'est lancé que quand tous les ExecStartPre se sont terminé séquentiellement).
        Un tel script pourrait également être mis en ExecStartPost d'influxd.service (via un fragment dans le répertoire influxd.service.d, pour ne pas modifier le fichier principal) si tu veux que ça profite à d'autres services. (c'est à vérifier, mais il me semble qu'un service n'est considéré comme démarré que quand les ExecStartPost se sont terminés)

        Si tu ne sais pas comment déterminer ton ton script si influxd est bien fonctionnel, tu as toujours la solution barbare de faire un sleep de quelques secondes (pas besoin de script dans ce cas) en espérant que ce sera toujours suffisant, mais l'ennui dans ce cas est que tu fera toujours une pause au démarrage de ton service, même si influxd est démarré depuis longtemps.
        Une solution intermédiaire serait de faire un script qui va utiliser systemctl (avec la commande show) pour savoir depuis combien de temps le service influxd est démarré, et faire une pause si ce n'est pas au moins quelques secondes.

        • [^] # Re: Type de service

          Posté par  . Évalué à 1.

          Un systemctl cat influxd.service retourne la même chose que ce que j'ai mis précédemment.

          Est-ce que si j'attends l'apparition du port 8086 je peux considérer qu'influx sera opérationnel?

          • [^] # Re: Type de service

            Posté par  . Évalué à 2.

            Je vais laisser quelqu'un qui sait ce qu'est influxd répondre à cette question …

  • # Mettre à jour la procédure de démarrage

    Posté par  (site web personnel, Mastodon) . Évalué à 0.

    Hello,

    Si je me souvuens bien, la commande systemctl daemon-reload demande juste à systemd de relire les fichiers de configuration.

    Le plus souvent, il faut juste redémarrer le service ensuite. Mais comme tu modifies les dépendances de démarrage, il faudrait aussi faire un systemctl disable et systemctl enable.

    En effet, ce sont ces 2 dernières commandes qui gèrent les liens entre services en créant les répertoires "services.wants" dans /etc/systemd/system.

    • [^] # Re: Mettre à jour la procédure de démarrage

      Posté par  . Évalué à 3. Dernière modification le 07 janvier 2018 à 00:39.

      Non, systemctl enable et disable ne font que (dés)activer une unité selon ce qui est défini dans sa section [install], les dépendances entre unités sont lues dans les fichiers des unités et les répertoires *.wants ne sont qu'une façon d'y contribuer (et la dépendance Wants n'est qu'une version plus faible de Requires, Wants existe principalement pour configurer ce qui doit être lancé au démarrage).
      cf la page de manuel de systemd.unit

      Edit: et pour être complet, il y a aussi des répertoires *.requires qui correspondent à la dépendance Requires.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.