[ Présentation | Analyser les performances au démarrage | Analyser le journal  Etat de marcheGérer les services | Créer un service | Créer un service interactif au lancement | Commandes diverses ]

Dernière modification 30 janvier 2016

Gestion des services et du démarrage avec Systemd

Configuration diverse du système

Présentation

Cette page a pour objet de vous présenter le principe de démarrage d'un système Linux basé sous systemd, ainsi vous pourrez améliorer les performances, personnaliser les scripts de lancement et bien d'autres choses. Elle présente également la gestion des services au quotidien.

Systemd est basé sur la notion d'unités (units) qui sont de différents types, les plus intéressants (et utiles pour le commun des mortels) sont:
- device: pour un périphérique physique ou virtuel
- mount: pour un système de fichiers monté
- service: pour un daemon
- socket: pour une socket
- swap: pour le swap
- target: regroupement de plusieurs unités

la commande systemctl list-units permet de lister l'ensemble des unités

par exemple on retrouve les unités de type mount

  home.mount                                                   loaded active mounted   /home
  mana-data.mount                                              loaded active mounted   /mana/data
  marcel.mount                                                 loaded active mounted   /marcel
  media-windows.mount                                          loaded active mounted   /media/windows

les unités de type services

  acpid.service                                                loaded active running   ACPI Event Daemon
  alsa-state.service                                           loaded active running   Manage Sound Card State (restore and store)
  atd.service                                                  loaded active running   Job spooling tools
  autofs.service                                               loaded active running   Automounts filesystems on demand

ou des targets qui regroupent plusieurs services

  graphical.target                                             loaded active active    Graphical Interface
  local-fs-pre.target                                          loaded active active    Local File Systems (Pre)
  local-fs.target                                              loaded active active    Local File Systems
  multi-user.target                                            loaded active active    Multi-User System
  network-online.target                                        loaded active active    Network is Online
  network.target                                               loaded active active    Network
  nfs.target                                                   loaded active active    Network File System Client and Server Support

[ Retour haut de la page ]

Analyser les performances de démarrage

Systemd est doté d'outils permettant de connaître assez facilement le temps nécessaire pour démarrer, il suffit de taper

systemd-analyze

voilà le résultat

Startup finished in 7.781s (kernel) + 33.311s (userspace) = 41.092s

mieux encore, on peut détailler le temps de démarrage de chaucn des services du plus lent au plus rapide en tapant systemd-analyze blame voilà le résultat

          7.628s network-up.service
          7.126s systemd-journald.service
          6.247s systemd-udev-settle.service
          5.513s cups.service
          4.626s mandriva-everytime.service
          4.437s colord.service
          2.942s fedora-readonly.service
          2.845s network.service
          2.822s shorewall.service
          2.354s plymouth-quit-wait.service
          2.286s systemd-journal-flush.service
          1.819s systemd-fsck@dev-disk-by\x2duuid-d2cdc5ad\x2d27db\x2d4dd0\x2da7d4\x2dbc1484c11207.service
          1.774s upower.service
          1.769s mga-bg-res.service
          1.767s bluetooth.service
          1.683s systemd-vconsole-setup.service
          1.640s chronyd.service
          1.559s systemd-fsck@dev-disk-by\x2duuid-9ec2061b\x2da31a\x2d4805\x2db40c\x2dc38fa287ae9c.service
          1.490s systemd-fsck@dev-disk-by\x2duuid-23b62993\x2d5cda\x2d4a78\x2d8a22\x2d38724581a791.service
          1.399s systemd-logind.service
          1.395s cpupower.service
          1.395s acpid.service
          1.394s nscd.service
          1.391s avahi-daemon.service
          1.284s media-windows.mount
          1.116s systemd-udevd.service
          1.051s autofs.service
           620ms var-lib-nfs-rpc_pipefs.mount
           547ms preload.service
           534ms resolvconf.service
           533ms nfs-lock.service
           486ms systemd-tmpfiles-setup-dev.service
           436ms home.mount
           433ms systemd-backlight@backlight:intel_backlight.service
           424ms usr-local.mount
           362ms systemd-udev-trigger.service
           354ms systemd-remount-fs.service
           352ms tmp.mount
           338ms dev-hugepages.mount
           338ms dev-mqueue.mount
           337ms sys-kernel-debug.mount
           305ms systemd-sysctl.service
           298ms systemd-fsck@dev-disk-by\x2duuid-3af649ab\x2d587c\x2d4639\x2d8ee8\x2d413397c5bd39.service
           295ms mandriva-save-dmesg.service
           262ms dev-disk-by\x2duuid-b59a03aa\x2d4744\x2d4ace\x2dad91\x2d10f8109817b8.swap
           245ms systemd-networkd.service
           245ms iptables.service
           242ms systemd-tmpfiles-setup.service
           237ms systemd-update-utmp.service
           213ms user@5001.service
           203ms nslcd.service
           199ms systemd-modules-load.service
           193ms rpcbind.service
           182ms udisks2.service
           178ms systemd-rfkill@rfkill0.service
           174ms systemd-rfkill@rfkill1.service
           165ms ip6tables.service
           164ms systemd-user-sessions.service
           161ms systemd-tmpfiles-clean.service
           160ms systemd-timesyncd.service
           159ms systemd-rfkill@rfkill3.service
           153ms nfs-idmap.service
           153ms polkit.service
           151ms systemd-random-seed.service
           148ms partmon.service
           133ms systemd-resolved.service
           122ms plymouth-read-write.service
            91ms marcel.mount
            65ms systemd-rfkill@rfkill2.service
            35ms fedora-loadmodules.service
            31ms msec.service
            23ms kmod-static-nodes.service
             4ms plymouth-start.service
             4ms fedora-wait-storage.service
             3ms rtkit-daemon.service
             2ms systemd-update-utmp-runlevel.service
             1ms sys-fs-fuse-connections.mount

on peut voir que c'est l'établissement du réseau qui est le plus lent puis vient ensuite la journalisation de systemd. Mieux encore si on tape

systemd-analyze plot > boot.svg

vous obtenez un fichier graphique vectoriel donnant le lancement séquentiel de chaque service avec le temps nécessaire pour le lancer. On peut l'ouvrir avec Gimp, cela donne cela (cliquez dessus pour voir le détail)



pour comprendre pourquoi le réseau prend du temps vous pouvez taper maintenant

systemd-analyze critical-chain network-up.service

voilà le résultat

The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

network-up.service +7.428s
partmon.service @20.121s +299ms
  network.service @17.097s +2.988s
    resolvconf.service @16.627s +468ms
      preload.service @16.071s +555ms
        prefdm.service @16.071s
          systemd-user-sessions.service @15.930s +84ms
            basic.target @14.067s
              mandriva-everytime.service @8.314s +5.752s
                local-fs.target @8.312s
                  fedora-wait-storage.service @8.307s +4ms
                    systemd-udev-settle.service @1.567s +6.739s
                      systemd-udev-trigger.service @1.161s +404ms
                        system.slice @1.107s
                          -.slice @1.107s

on voit que le service mandriva-everytime.service prend quand même pas mal de temps. Si on regarde de plus près ce service avec le fichier /usr/lib/systemd/system/mandriva-everytime.service, il lance le script /etc/init.d/mandrake_everytime un moyen très simple de réduire considérablement le temps de boot est de supprimer le lancement systématque de harddrake qui vérifie si votre config hard n'a pas changé. Vous pouvez allègrement le supprimer, ça n'aura pas d'impact sur le rajout de périphériques externes, et si le jour où vous voudrez modifier votre config hard il faudra veiller à le réactiver.

Juste avant

HARDDRAKE_TOOL=/usr/share/harddrake/service_harddrake
if [ "$HARDDRAKE_ONBOOT" != "no" ] && [ -x $HARDDRAKE_TOOL ]; then
    gprintf "Checking for new hardware"
    SYSTEMCTL_NO_BLOCK=1 $HARDDRAKE_TOOL 2>/dev/null
    RETVAL=$?
    if [ "$RETVAL" -eq 0 ]; then
        action "" /bin/true
    else
        action "" /bin/false
    fi
fi

on rajoute HARDDRAKE_ONBOOT="no"

et le temps est joué. Un autre moyen simple est de supprimer les interfaces réseau qui ne servent à rien, en désactivant le wifi si vous êtes en connexion réseau RJ45 par exemple, ou bien encore de désactiver la journalisation mais je ne vous le conseille pas.
[ Retour haut de la page]

Analyser le journal

Avec systemd terminé le fichier /var/log/messages, on utilise la commande journalctl, il faudra basculer root pour pouvoir s'en servir, une autre solution est de rajouter votre utilisateur dans le groupe systemd-journal. La commande dont je me sers le plus remplace "tail -f /var/log/messages", il s'agit de journalctl -f elle affiche en temps réel la journalisation de systemd.
Quelques commandes utiles

Pour afficher le journal depuis le dernier boot journalctl -b

Connaître la taille du journal journalctl --disk-usage voilà le résultat

Journals take up 504.0M on disk.

le journal se trouve sous /var/log/journal dans un répertoire qui a un nom biscornu du style bf82d7513a9a4a9aaea47267d3b3d8c5. Si ça vous semble énorme, vous pouvez toujours modifier les paramètres de journalisation qu'on trouvera dans le fichier /etc/systemd/journald.conf si on met

MaxRetentionSec=1month
MaxFileSec=1month

cela permet de limiter la journalisation à un 1mois ce qui est généralement largement suffisant. Si modification du fichier on doit relancer la journalisation en tapant

systemctl restart systemd-journald


[ Retour haut de la page ]

Etat de marche

Les états de marche (runlevel) existent toujours, on a donc toujours

le runlevel 0 correspond à l'arrêt du système
le runlevel 1 correspond au niveau de maintenance (mode single)
le runlevel 2 à 4 correspond au mode réseau, multi utilisateur sans interface graphique
le runlevel 5 est l'état de marche classiquement par défaut, c'est le mode graphique, en réseau, multi utilisateur
le runlevel 6 entraîne le reboot du système

sur une mageia on retrouve les runlevels qui pointent ainsi

lrwxrwxrwx 1 root root   15 juin   3  2015 runlevel0.target -> poweroff.target           
lrwxrwxrwx 1 root root   13 juin   3  2015 runlevel1.target -> rescue.target
lrwxrwxrwx 1 root root   17 juin   3  2015 runlevel2.target -> multi-user.target
lrwxrwxrwx 1 root root   17 juin   3  2015 runlevel3.target -> multi-user.target
lrwxrwxrwx 1 root root   17 juin   3  2015 runlevel4.target -> multi-user.target
lrwxrwxrwx 1 root root   16 juin   3  2015 runlevel5.target -> graphical.target
lrwxrwxrwx 1 root root   13 juin   3  2015 runlevel6.target -> reboot.target

ainsi

systemctl rescue.target

ou bien sous mageia

systemctl runlevel1.target

permet d'avoir un état de système avec le minimum de services lancés, pas de réseau, pas d'interface graphique en mode single (root). Avec

systemctl isolate multi-user.target

vous retrouvez le réseau mais pas l'interface graphique et enfin

systemctl isolate graphical.target

permet de lancer le réseau et l'interface graphique, en gros c'est l'état standard.

Si vous disposez d'un serveur et que vous ne voulez pas lancer l'interface graphique, vous pouvez définir le nouvel état de marche par défaut en tapant

systemctl set-default multi-user.target


[ Retour haut de la page ]


Gérer les services

Vous trouverez l'ensemble des unités de votre système sous /usr/lib/systemd/system, pour une meilleure lisibilité vous pouvez également lancer la commande suivante systemctl list-units --type=service

voilà le résultat

  UNIT                                                          LOAD   ACTIVE SUB     DESCRIPTION
  acpid.service                                                 loaded active running ACPI Event Daemon
  alsa-state.service                                            loaded active running Manage Sound Card State (restore and store)
  atd.service                                                   loaded active running Job spooling tools
  autofs.service                                                loaded active running Automounts filesystems on demand
  avahi-daemon.service                                          loaded active running Avahi mDNS/DNS-SD Stack
  bluetooth.service                                             loaded active running Bluetooth service
  chronyd.service                                               loaded active running NTP client/server
  colord.service                                                loaded active running Manage, Install and Generate Color Profiles
  cpupower.service                                              loaded active exited  Configure CPU power related settings
  crond.service                                                 loaded active running Command Scheduler
  cups-browsed.service                                          loaded active running Make remote CUPS printers available locally
  cups.service                                                  loaded active running CUPS Scheduler
  dbus.service                                                  loaded active running D-Bus System Message Bus
...

Pour activer un nouveau service pour qu'il se lance automatique à chaque boot on tapera

systemctl enable nom-service

pour le désactiver

systemctl disable nom-service

pour voir si un service est activé au boot

systemctl is-enabled nom-service

voilà le résultat

enabled

pour voir l'état d'un service (par exemple ici autofs)

systemctl status autofs

voilà le résultat

autofs.service - Automounts filesystems on demand
   Loaded: loaded (/usr/lib/systemd/system/autofs.service; enabled)
   Active: active (running) since sam. 2016-01-30 12:14:22 CET; 3h 7min ago
  Process: 2044 ExecStart=/usr/sbin/automount $OPTIONS --pid-file /run/autofs.pid (code=exited, status=0/SUCCESS)
 Main PID: 2049 (automount)
   CGroup: /system.slice/autofs.service
           2049 /usr/sbin/automount --pid-file /run/autofs.pid

janv. 30 14:06:00 uapou.kervao.fr automount[2049]: key ".hidden" not found in map source(s).
janv. 30 14:19:20 uapou.kervao.fr automount[2049]: key ".hidden" not found in map source(s).
janv. 30 14:19:21 uapou.kervao.fr automount[2049]: key ".thumblocal" not found in map source(s).
janv. 30 14:21:42 uapou.kervao.fr automount[2049]: key ".hidden" not found in map source(s).
janv. 30 14:23:01 uapou.kervao.fr automount[2049]: key ".hidden" not found in map source(s).
janv. 30 14:25:35 uapou.kervao.fr automount[2049]: key ".hidden" not found in map source(s).

on retrouve les lignes du journal relatives au lancement du daemon d'automontage

pour stopper un service (mais il reste actif au prochain reboot)

systemctl stop nom-service

pour le lancer

systemctl start nom-service

pour le relancer

systemctl restart nom-service

[ Retour haut de la page ]

Créer un service

Pour un lancement automatique il faudra créer préalablement le fichier /etc/systemd/system/nom.service qui ressemblera à ça

[Unit]
Description=nom du service
After=nom du service qui est lancé précédemment

[Service]
Type=forking si plusieurs process lancés par fork ou oneshot si lancement d'une seule instance
PIDFile=/var/run/nom-service.pid
ExecStart=cmd à lancer pour lancer le service

[Install]
WantedBy=nom de l'état de marche dont il dépend

on le rend exécutable en tapant

chmod 755
/etc/systemd/system/nom.service

et on l'active en tapant

systemctl enable httpd.service

voilà le résultat

Created symlink from /etc/systemd/system/multi-user.target.wants/spamassassin.service to /usr/lib/systemd/system/spamassassin.service.

après chaque modif d'un fichier de configuration d'un service, il faudra taper le commande

systemctl --system daemon-reload


[ Retour haut de la page ]


Créer un service interactif au lancement

On va prendre un exemple simple et concret, j'ai un portable avec mageia qui quand il est "à la maison" utilise les services d'authentification utilisateur par LDAP et d'automontage NFS de mon serveur, sauf que quand je suis en déplacement avec mon, portable, les services NFS et LDAP restent actifs et génèrent des timeouts bien pénibles. L'idée est de pouvoir choisir entre un mode maison et mobile au lancement du système.

En tout seigneur tout honneur, je me suis inspiré de ce site https://mespotesgeek.fr/fr/execution-dun-script-interactif-au-boot-avec-systemd/ qui a été lui même inspiré par https://alan-mushi.github.io/2014/10/26/execute-an-interactive-script-at-boot-with-systemd.html

j'ai donc créé le service /etc/systemd/system/choix.service contenant

[Unit]
Description=Service pour passer en mode maison ou mobile
After=getty@tty2.service

[Service]
Type=oneshot
ExecStart=/usr/bin/choix-mode.sh
StandardInput=tty
TTYPath=/dev/tty2
TTYReset=yes
TTYVHangup=yes

[Install]
WantedBy=multi-user.target

pour le détail des paramètres, je vous renvoie aux sites cités plus haut. Revenons à notre script /usr/bin/choix-mode.sh il va contenir

#!/bin/bash

sleep 5

chvt 2

mode=$(whiptail --title "Mode connexion" --radiolist \
        "Quel est ton mode connexion" 15 60 4 \
        "Connecte" "Je suis à la maison" ON \
        "Mobile" "Je suis en mode mobile" OFF 3>&1 1>&2 2>&3)
 
exitstatus=$?
if [ $exitstatus -ne 0 ]; then
      mode="Connecte"
fi

if [ $mode == 'Mobile' ]; then
    systemctl stop nslcd
   systemctl stop autofs
fi

chvt 1

par défaut mageia boote sur la console tty1, on bascule à un moment sur la console tty2 (chvt 2) la fenêtre s'affiche, on fait notre choix et rebascule sur la console de boot normal tty1 (chvt 1). La commande sleep au tout début est nécessaire sinon on n'a pas la main sur la fenêtre. Si 3>&1 1>&2 2>&3 n'apparait pas à la fin de la commande whiptail rien ne s'affiche. On donne des droits d'exe à notre script en tapant:

chmod 755 choix-mode.sh

attention il faudra veiller à avoir le package newt installé pour bénéficier la commande gérant les fenêtres de dialogue whiptail. On active maintenant le service en tapant  systemctl enable choix.service. On reboote et voilà le résultat


 
La photo est un peu pourrave, mais on voit que ça marche ! Par contre problème sous mageia les messages de systemd s'affichent par dessus la fenêtre, c'est plutôt pénible, j'ai bien essayé de jouer avec les différentes consoles mais à croire que les messages s'affichent sur toutes les consoles. Le plus simple est de passer le boot en mode silencieux pour supprimer les messages. Pour cela on édite le fichier /boot/grub/menu.lst et on rajoute les commandes suivantes (en italique)

kernel (hd0,4)/boot/vmlinuz BOOT_IMAGE=linux root=UUID=56f67d09-fddc-49f2-83c3-8c3c20378f90  splash quiet loglevel=0 noiswmd resume=UUID=b59a03aa-47
44-4ace-ad91-10f8109817b8 vga=788 systemd.show_status=0

ce n'est pas fini, on crée le fichier /etc/sysctl.d/20-quiet-printk.conf qui contient

kernel.printk = 3 3 3 3

on reboote et plus de messages indésirables.
[ Retour haut de la page ]

Commandes diverses

La commande hostnamectl permet d'avoir des infos sur l'hôte, voilà le résultat


   Static hostname: uapou.kervao.fr
         Icon name: computer-laptop
           Chassis: laptop
        Machine ID: bf82d7513a8a4a9baea47267d3b3d8c5
           Boot ID: 272ead9f795846e1c49a5d27e3c50056
  Operating System: Mageia 5
            Kernel: Linux 3.19.8-desktop-3.mga5
      Architecture: x86-64

La commande localectl permet d'avoir des infos sur les locales (langue), voilà le résultat

   System Locale: LANG=fr_FR.UTF-8
                  LANGUAGE=fr_FR.UTF-8:fr
       VC Keymap: fr-latin1
      X11 Layout: fr
       X11 Model: pc105
     X11 Options: compose:rwin

la commande timedatectl permet d'avoir des infos de date, voilà le résultat

      Local time: sam. 2016-01-30 15:39:06 CET
  Universal time: sam. 2016-01-30 14:39:06 UTC
        RTC time: sam. 2016-01-30 15:39:06
       Time zone: Europe/Paris (CET, +0100)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: yes
      DST active: no
 Last DST change: DST ended at
                  dim. 2015-10-25 02:59:59 CEST
                  dim. 2015-10-25 02:00:00 CET
 Next DST change: DST begins (the clock jumps one hour forward) at
                  dim. 2016-03-27 01:59:59 CET
                  dim. 2016-03-27 03:00:00 CEST

[Retour page d'accueil FUNIX] [ Retour haut de la page]