URL: https://linuxfr.org/news/aujourd-hui-c-est-deja-demain-systemd-dans-l-initrd-sous-arch-linux Title: Aujourd’hui c’est déjà demain : systemd dans l’initrd sous Arch Linux Authors: Jean-Philippe Garcia Ballester Davy Defaud, palm123, Xavier Teyssier et Bruno Michel Date: 2014年10月16日T14:38:21+02:00 License: CC By-SA Tags: systemd, archlinux et initrd Score: 23 Nous allons voir dans ce petit article comment utiliser _systemd_ dans l’_initrd_. La construction d’un _initrd_ étant spécifique à la distribution, nous verrons comment l’utiliser avec Arch Linux, mais avec un peu de travail cela devrait pouvoir donner le principe général de fonctionnement et être adaptable sur d’autres distributions. ---- [Journal à l’origine de la dépêche](http://linuxfr.org/users/giga/journaux/aujourd-hui-c-est-deja-demain-systemd-dans-l-initrd-sous-arch-linux) ---- **ATTENTION** : nous allons modifier une partie très importante du démarrage de la machine, et il est probable qu’elle ne puisse plus démarrer. Prévoyez donc un _live_ CD quelconque pour pouvoir réparer en cas de souci ! Quelques généralités sur l’initrd ================================= L’_initrd_, c’est une archive _cpio_ qui est chargée en mémoire vive par le noyau juste après son lancement. Elle est montée sur `/`, puis le fichier `/init` est exécuté. Ce dernier est censé s’occuper de lancer tout ce qui est nécessaire au montage de du vrai système de fichiers racine `/`, et qui n’est pas en dur dans le noyau, comme le chargement de modules noyau : accès au LVM, le déchiffrement de partitions, montage de `/usr` s’il est sur une partition séparée... Traditionnellement, ce fichier _init_ est un script _shell_ construit par des outils spécifiques à la distribution. La construction classique de l’initrd sous Arch Linux ----------------------------------------------------- Sous Arch Linux, la construction d’un _initrd_ se fait à l’aide du logiciel _mkinitcpio_. Il se configure en utilisant le fichier `/etc/mkinitcpio.conf`. La variable `HOOKS` est celle qui nous intéresse présentement. Pour chaque _hook_ présent dans cette variable, deux fichiers seront utilisés, un script `install` qui sera chargé d’ajouter les fichiers nécessaires à l’_initrd_ lors de la construction, et un script `hook` qui sera lancé par le script _shell_ `init` lors de l’amorçage du système. L’ordre d’apparition des _hooks_ dans la variable `HOOKS` est important, car c’est l’ordre utilisé pour lancer les scripts lors de l’amorçage. L’utilisation de systemd dans l’initrd -------------------------------------- Lorsqu’on utilise _systemd_ dans l’_initrd_, le fichier `/init` de l’_initrd_ n’est plus un script _shell_, mais directement _systemd_. Ainsi, lors de la construction de l’_initrd_ avec `mkinitcpio`, le script `hook` n’a plus aucun effet, et le script `install` est chargé, outre les fichiers nécessaires, tels les démons et modules noyaux, d’installer les unités _systemd_ nécessaires à monter la vraie racine. L’ordre d’apparition des _hooks_ dans la variable `HOOKS` n’a plus d’importance (à une exception près que nous verrons plus bas), car ce sont les unités _systemd_ qui détermineront l’ordre de lancement des différentes unités (et donc de tous les binaires lancés, car tout est lancé via _systemd_). systemd dans l’initrd, ça sert à quoi ? -------------- Il y a sûrement des avantages secondaires, comme la parallèlisation, une configuration de démarrage unique et centralisée, et peut‐être d’autres, mais l’avantage principal est quand même de faire rager les anti‐systemd en le mettant partout et à toutes les sauces. Configuration du système pour utiliser systemd ============================================== Le problème principal est que le support d’Arch Linux pour _systemd_ dans l’_initrd_ est un peu balbutiant, et il faut donc mettre un peu les mains dans le cambouis pour que tout fonctionne. Nous verrons ici comment configurer un système utilisant une partition chiffrée contenant du LVM et Plymouth, puisque c’est ma configuration. L’ajout du RAID ne doit pas être très compliqué. La base ======= Les _hooks_ `base`, `usr`, `udev` et `timestamp` ne sont plus nécessaires et sont remplacés par le _hook_ `systemd`. Les _hooks_ `autodetect`, `block`, `filesystems`, `btrfs` et `keyboard` sont toujours nécessaires (au moins sur ma machine). Les autres _hooks_ (`lvm`, `encrypt`, `plymouth`, etc.) seront par la suite remplacés par des équivalents `sd-machin`. Les _hooks_ `sd-machin` doivent toujours être après le _hook_ `systemd`. En effet, ce _hook_ ajoute une fonction utilisable dans les autres _hooks_, `add_systemd_unit`. Cette fonction ajoute dans l’_initrd_ l’unité passée en paramètre, ainsi que toutes ses dépendances. Correctif 1 : unités dans `/etc` ---------------------------- Cette fonction a un problème : elle n’utilise que le dossier `/usr/lib/systemd/system` et ignore donc totalement les unités créées par l’utilisateur, situées dans le dossier `/etc/systemd/system` (voir le [rapport de bogue](https://bugs.archlinux.org/task/42396)). Nous allons donc modifier le _hook_, en copiant `/usr/lib/initcpio/install/systemd` vers `/etc/initcpio/install/systemd`. Nous allons donc pouvoir effectuer nos modifications sans risquer de les voir écrasées par une mise à jour. Le correctif est le suivant : ```diff --- /usr/lib/initcpio/install/systemd 2014年09月02日 00:11:28.000000000 +0630 +++ /etc/initcpio/install/systemd 2014年10月16日 13:39:11.291460470 +0630 @@ -51,7 +51,7 @@ local unit= rule= entry= key= value= binary= dep= - unit=$(PATH=/usr/lib/systemd/system:/lib/systemd/system type -P "1ドル") + unit=$(PATH=/etc/systemd/system:/usr/lib/systemd/system:/lib/systemd/system type -P "1ドル") if [[ -z $unit ]]; then # complain about not found unit file return 1 @@ -78,18 +78,23 @@ done <"$unit" # preserve reverse soft dependency - for dep in {/usr,}/lib/systemd/system/*.wants/${unit##*/}; do + for dep in {{/usr,}/lib,/etc}/systemd/system/*.wants/${unit##*/}; do if [[ -L $dep ]]; then add_symlink "$dep" fi done # add hard dependencies - if [[ -d $unit.requires ]]; then - for dep in "$unit".requires/*; do - add_systemd_unit ${dep##*/} - done - fi + for dir in {{/usr,}/lib,/etc}/systemd/system/${unit##*/}.requires; do + if [[ -d "$dir" ]]; then + for dep in "$dir"/*; do + if [[ -L $dep ]]; then + add_symlink "$dep" + fi + add_systemd_unit ${dep##*/} + done + fi + done } build() { ``` Correctif 2 : `emergency.target` ---------------------------- Second problème de ce _hook_, il n’ajoute pas les utilitaires nécessaires au fonctionnement d’`emergency.target`, une unité spéciale qui est lancée lorsque l’amorçage plante et donne un _shell_ à l’utilisateur pour essayer de sauver les meubles (voir un [rapport de bogue](https://bugs.archlinux.org/task/42399) et [un autre](https://bugs.archlinux.org/task/36265)). On va donc le modifier pour rajouter `sulogin`, ainsi que les utilitaires de `busybox`. ```diff --- /etc/initcpio/install/systemd.old 2014-10-16 13:44:23.135993657 +0630 +++ /etc/initcpio/install/systemd 2014-10-16 13:43:23.657715653 +0630 @@ -98,12 +98,22 @@ } build() { - local rules unit + local rules unit applet # from base add_binary /bin/mount add_binary /usr/bin/kmod /usr/bin/modprobe + add_binary /usr/lib/initcpio/busybox /bin/busybox + for applet in $(/usr/lib/initcpio/busybox --list); do + add_symlink "/usr/bin/$applet" busybox + done + + # sulogin is needed for emergency target + add_binary /sbin/sulogin + add_file /etc/shadow + add_file /etc/gshadow + # systemd add_binary /usr/lib/systemd/systemd /init add_binary /usr/bin/systemd-tmpfiles ``` À ce stade, si l’on a une partition racine simple, on a terminé. Partition chiffrée ================== S’il y a une partition chiffrée nécessaire au démarrage, il faut ajouter le _hook_ `sd-encrypt`. Attention, les paramètres de ligne de commande du noyau (probablement configurés dans `/etc/default/grub`) pour indiquer les partitions et leurs options ont changé. Le paramètre `cryptdevice` est remplacé par `luks.machin` (`man systemd-cryptsetup-generator` pour plus d’infos). Cependant, plutôt que ces paramètres, il est plus utile d’utiliser le fichier `/etc/crypttab.initramfs`, qui suit la syntaxe de `/etc/crypttab`. LVM === Il suffit d’ajouter le fichier `sd-lvm`. Aucune configuration particulière, car un détection est lancée dès l’apparition d’un nouveau _block device_, et activé si celui‐ci est un LVM (donc on peut avoir une partition chiffrée dans un LVM et un LVM dans une partition chiffrée, sans avoir à préciser d’ordre particulier ; et même avoir une partition chiffrée dans un LVM dans une partition chiffrée). Résumé ====== Il n’y a rien dans la version stable de _systemd_ pour s’occuper de sortir le système de l’hibernation. C’est prévu pour la prochaine version, mais en attendant, il va falloir faire les choses à la main. On crée donc une unité `/etc/systemd/system/resume.target` : ```ini [Unit] Description=Resume from disk Before=initrd-root-fs.target sysroot.mount [Install] WantedBy=initrd.target ``` Et on l’active avec `systemctl enable resume.target`. Puis une unité générique `/etc/systemd/system/resume@.service` : ```ini [Unit] Description=Resume from disk using %I Before=resume.target DefaultDependencies=no BindsTo=%i.device After=%i.device [Service] Type=oneshot ExecStart=/bin/sh -c "echo $(mountpoint -x %I)> /sys/power/resume" [Install] RequiredBy=resume.target ``` On l’active en utilisant le chemin de sa partition d’échange (_swap_), dans mon cas : `systemctl enable resume@dev-main-swap.service`. On crée enfin le _hook_ _mkinitcpio_ `/etc/initcpio/install/sd-resume` : ```bash #!/bin/bash build() { add_systemd_unit resume.target } help() { cat <

AltStyle によって変換されたページ (->オリジナル) /