-
MINT > lenteur au démarrage
deux commandes :
systemd-analyze
etsystemd-analyze blame
.Exemple :
systemd-analyse Startup finished in 35.072s (kernel) + 11.461s (userspace) = 46.533s graphical.target reached after 1.380s in userspace
Le kernel met donc 35s au démarrage et l’espace utilisateur (userspace) 11s. Donc deux problèmes : le kernel et le userspace.
Temps d’initialisation de chaque service :
systemd-analyse blame 10.153s ntp.service 408ms dev-nvme0n1p3.device 292ms NetworkManager.service 252ms systemd-cryptsetup@cryptswap1.service 245ms systemd-resolved.service
On identifie de suite la raison de la lenteur au démarrage de l’userspace :
ntp.service
. Ce service met 10s à s’initialiser à lui tout seulLa majorité des services systemd démarrent en moins d’une seconde avec un SSD.
Certains sont longs : virtualisation, bases de données… Tout service qui démarre en plus de 2-3 secondes mérite une attention.
Diagnostiquer
Ici nous allons désactiver le service ntp :
sudo systemctl disable ntp.service
pour rollback :
sudo systemctl enable ntp.service
redémarrer:
sudo reboot
puis afficher de nouveau le résultat
systemd-analyze blame
.Il est évident mais ça confirme qu’il n’y a pas d’effets indésirables dans l’immédiat : L’userspace démarre en moins de 2 secondes.
On gagne près de 10s à chaque démarrage.
Repassons sur notre lenteur kernel : Dans Grub, choisir
Advanced options for Linux Mint 19 Xfce>Linux Mint 19 XFCE (recovery mode)et on regarde ce qui se passe. Dans mon cas c’est simple, ça reste longtemps sur un message : Scanning for btrfs file systems. On va orienter nos recherches de ce côté-là.Réparer
ntp fournit l’heure exacte au système, on ne peut pas se contenter de le laisser désactivé mais on peut probablement lui trouver un remplaçant. Je vous recommande chaudement chrony, vous pouvez aussi passer à systemd-timesyncd. Chrony est méconnu pourtant c’est la nouvelle référence, il est déjà utilisé de base sur les systèmes Fedora, CentOS, Red Hat. Sa configuration par défaut est sécurisée, correcte, il n’écoute qu’en local et n’agit qu’en client NTP. Il faut donc juste l’installer :
sudo apt install chrony
On redémarre
sudo reboot
puis on affiche de nouveau le résultatsystemd-analyze blame
La lenteur constatée niveau userspace a disparu, on a définitivement gagné 10s à chaque démarrage, le service chrony s’initialise en 54ms. On aurait pu creuser le problème du service NTP, ça aurait pris sûrement beaucoup plus de temps.
En effectuant quelques recherches sur la lenteur niveau kernel, on apprend qu’il y a des problèmes avec le noyau 4.15.0-20. On vérifie notre noyau (
uname -r
), pas le même. Le plus évident lorsqu’on a un problème avec un noyau, c’est d’en tester un autre.On se rend sur http://kernel.ubuntu.com/~kernel-ppa/mainline/ puis on cherche la dernière branche. Le plus simple étant de cliquer sur Last modified, actuellement le noyau le plus récent est le 4.18. Je n’aime pas prendre la dernière version, je lui préfère une version antérieure (par exemple la 4.17.12) :
1/ Les bugs commencent à être connus et identifiés, on peut retrouver leurs traces
2/ Trop récent, peu fiable.
On télécharge, on installe, on redémarre, on vérifie le noyau et systemd-analyze.
wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.17.12/linux-headers-4.17.12-041712-generic_4.17.12-041712.201808030231_amd64.deb http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.17.12/linux-headers-4.17.12-041712_4.17.12-041712.201808030231_all.deb http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.17.12/linux-image-unsigned-4.17.12-041712-generic_4.17.12-041712.201808030231_amd64.deb http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.17.12/linux-modules-4.17.12-041712-generic_4.17.12-041712.201808030231_amd64.deb sudo dpkg -i linux*4.17.12*.deb sudo reboot uname -r systemd-analyze
Pas de bol, pas mieux ! On a encore un démarrage kernel de plus de 30 secondes. À noter que sur Grub, on peut toujours choisir de booter sur l’ancien noyau. On va faire des recherches sur Scanning for btrfs file systems, je précise que je n’utilise pas btrfs sur mon pc. Le premier lien est la solution qui a marché pour moi.
sudo blkid # affiche les UUID des périphériques bloc (systèmes de fichiers) sudo cat /etc/initramfs-tools/conf.d/resume # compare UUID de la commande blkid avec le contenu du fichier resume. Ici aucune correspondance. L'UUID ne correspond à aucun périphérique bloc, c'est incohérent sudo cp /etc/initramfs-tools/conf.d/resume ~/resume.bak # On fait une sauvegarde du fichier pour pouvoir rollback sudo nano /etc/initramfs-tools/conf.d/resume # Remplacer RESUME=UUID=xxx par RESUME=none sudo update-initramfs -u
Je pense qu’une bonne explication est ici. Je recommande également ces liens connexes : 1, 2, 3, 4.
Pour résumer il y a des problèmes si vous chiffrez votre /home notamment autour de la swap. Dans la release notes de Mint 19 XFCE, Known issues : There is an issue with home directory encryption that causes swap to be misconfigured during installation. To correct this… »
Conclusion
Voir : Mint XFCE… ou pasÉvident. Classé dans : Linux Organisation Planet Libr
Tu peux de toute façon démarrer mysql à la volée avec du
systemctl start mysql. Le démarrage automatique de services, il faut jeter un œil de temps en temps car parfois tout n’est pas nécessaire.Danse avec les reboots
Un reboot est composé de deux phases : l’extinction (shutdown) et le démarrage (boot). Peu de gens s’intéressent à l’extinction de leur pc, normal on arrête de l’utiliser. En revanche le temps de redémarrage d’un serveur est important, plus il sera long, plus longue sera la période d’indisponibilité des services fournis. Pour moi 60s c’est que dalle mais sur un serveur mutualisé avec disons 100 clients dessus, c’est 100 clients qui seront impactés pendant 1 minute. Cette minute devient très importante.
Pour réduire le temps de redémarrage, kexec (1, 2, 3) est l’outil le plus utilisé. Chez Ubuntu il y a Canonical Livepatch qui peut éviter d’avoir à redémarrer. Le démarrage est la partie visible de l’iceberg et la plus « simple ». On a en effet une session, nos outils, des logs, on peut déboguer. La base sera de jouer avec
journalctl
,dmesg -T | grep quelquechose
, un petitjournalctl -p err
vous mettra sûrement sur la voie.Déboguer l’extinction sera plus difficile. Le système s’éteint, on n’a plus de connexion réseau, pas la main sur un quelconque outil et ça dure une poignée de secondes. Pour « voir » une extinction, il faut avoir un écran branché sur le serveur ou utiliser certains outils basés sur IPMI (ipmitool), Dell iDRAC, HP iLO, KVM over IP. Évidemment c’est un peu mieux puisqu’on « voit » quelque chose cependant ça va très (trop) vite. Avec un peu de chance vous verrez « A stop job is running for… » mais on doit trouver plus exploitable.
journalctl
Si vous faites
journalctl
, vous afficherez les logs depuis le démarrage mais comment avoir les logs de l’extinction ? Dans un article précédent, j’avais souligné un choix par défaut discutable dans /etc/systemd/journald.conf. Faites un petitman journald.conf
.Storage= Controls where to store journal data. One of "volatile", "persistent", "auto" and "none". If "volatile", journal log data will be stored only in memory, i.e. below the /run/log/journal hierarchy (which is created if needed). If "persistent", data will be stored preferably on disk, i.e. below the /var/log/journal hierarchy (which is created if needed), with a fallback to /run/log/journal (which is created if needed), during early boot and if the disk is not writable. "auto" is similar to "persistent" but the directory /var/log/journal is not created if needed, so that its existence controls where log data goes. "none" turns off all storage, all log data received will be dropped. Forwarding to other targets, such as the console, the kernel log buffer, or a syslog socket will still work however. Defaults to "auto".
Par défaut Storage=auto, le journal est stocké dans /run/log/journal qui est perdu à chaque extinction puisque /run est un système de fichier temporaire (tmpfs). On a deux solutions pour avoir des logs de l’extinction, mettre Storage=persistent dans /etc/systemd/journald.conf ou simplement créer le dossier /var/log/journal (« so that its existence controls where log data goes », si /var/log/journal existe les logs seront envoyés dedans). Afin que la modification soit prise en compte sans rebooter (ha ha ha), on aura éventuellement besoin de faire
systemctl restart systemd-journald
. Faitesjournalctl --list-boots
pour afficher les derniers boots, vous n’en aurez qu’un seul (le dernier). Maintenant si vous redémarrez votre pc/serveur puis que vous refaitesjournalctl --list-boots
, vous en aurez deux.On va pouvoir regarder les logs de la précédente extinction
journalctl -p err
sera encore utile mais perso je préfèrejournalctl -b -1 -n250 | grep 'timed out' # ou grep 'kill'
. Cette seconde commande affiche les 250 dernières lignes (-n250) des logs du précédent boot (-b -1). C’est ainsi que j’ai trouvé mon fautif, j’ai confirmé en désactivant et stoppant le servicesystemctl disable --now servicerelou
puis en rebootant : 40 secondes au lieu de 100.Allons plus loin
Tout d’abord pour mieux comprendre journald,
man systemd-journald
. On y trouvera notamment une explication plus claire du point précédent : « By default, the journal stores log data in /run/log/journal/. Since /run/ is volatile, log data is lost at reboot. To make the data persistent, it is sufficient to create /var/log/journal/ where systemd-journald will then store the data ».A noter que le Storage=auto fait actuellement débat, Ubuntu est revenu dessus, les arguments avancés sont très intéressants à lire.
Si /var/log/journal existe ou si vous passez Storage=persistent, attention cela signifie que vous allez avoir rsyslog qui fera son boulot ET journald. Perso je crée le dossier /var/log/journal au besoin et une fois que j’ai fini de déboguer, je le supprime.
DefaultTimeoutStartSec et DefaultTimeoutStopSec
J’ai trouvé le service responsable mais j’ai dû déboguer, je n’ai évidemment pas fait cela sur des serveurs en prod. Peut-on réduire le temps de reboot en se passant de la phase de recherche/debug ?
Déjà afin de connaître le temps d’arrêt et de démarrage d’un service, on peut utiliser
time systemctl stop servicerelou
ettime systemctl start servicerelou
.Je vous invite maintenant à lire ceci. Les options DefaultTimeoutStartSec= et DefaultTimeoutStopSec= permettent d’influer sur le timeout par défaut du démarrage/arrêt d’un service. Si vous modifiez ces valeurs dans le fichier /etc/systemd/system.conf, c’est le timeout par défaut de tous les services que vous modifiez.
Concrètement systemd attend 90s (par défaut) qu’un service s’arrête (stop), si au bout de ces 90s il n’est pas arrêté il va le tuer (kill). On comprend dès lors que si on met DefaultTimeoutStopSec=30s, systemd n’attendra au maximum que 30 secondes avant de tuer le service nous économisant de précieuses secondes. On peut donc au choix surcharger servicerelou (à l’aide des drop-ins) ou modifier le timeout par défaut pour tous les services (via /etc/systemd/system.conf).
Attention ! Tuer un service peut provoquer une perte de données. Si votre service postgresql est éléphantesque, qu’il a besoin de 43 secondes pour s’arrêter et que vous avez mis DefaultTimeoutStopSec=30s, il sera tué au bout de 30s.
On en vient à se demander si la valeur par défaut (90s) est pertinente, est-elle juste ? Chacun se fera sa propre idée, on pourrait considérer qu’un service qui ne s’arrête pas en 60s ne s’arrêtera probablement pas davantage en 90s.
On peut ruser ainsi en mettant DefaultTimeoutStopSec=60s dans /etc/systemd/system.conf suivi d’un
systemctl daemon-reexec
, redémarrer le serveur puis remettre DefaultTimeoutStopSec=90s suivi d’unsystemctl daemon-reexec
. On sera d’accord pour dire que ce n’est pas propre mais les contraintes de la prod obligent parfois à utiliser des « trucs » et des rustines pour arrondir les angles.