Question:
Comment puis-je utiliser un disque virtuel init (initramfs) au démarrage de Raspberry Pi?
Ingo
2019-01-03 01:55:46 UTC
view on stackexchange narkive permalink

J'ai besoin de charger le pilote au démarrage précoce. Pour le développement, j'utilise LVM (gestionnaire de volume logique) afin de pouvoir facilement rétablir les configurations de test à l'image par défaut à partir d'un instantané. Pour cela, je dois charger le pilote lvm avant d'accéder à la partition racine. Ceci est fait avec un ramdisk init (initrd ou initramfs). Ceci est également utile pour prendre en charge le noyau personnalisé. Mais contrairement à Debian, Raspbian ne prend pas en charge les initramfs prêts à l'emploi. Comment puis-je utiliser un disque virtuel d'initialisation?

Cinq réponses:
Ingo
2019-01-03 01:55:46 UTC
view on stackexchange narkive permalink

J'ai trouvé qu'il y a une configuration dans

  rpi ~ $ cat / etc / default / raspberrypi-kernel # Par défaut pour raspberrypi-kernel # Décommentez la ligne suivante pour activer la génération de # fichiers /boot/initrd.img-KVER (nécessite initramfs-tools) # INITRD = Yes # Décommentez la ligne suivante pour activer la génération de # /boot/initrd(7).img ( nécessite rpi-initramfs-tools) # RPI_INITRD = Oui  

Les commentaires sont la seule documentation que j'ai trouvée. En particulier, je ne trouve rien sur rpi-initramfs-tools . Ils ne sont tout simplement pas disponibles. J'ai donc testé avec INITRD = Yes en le décommentant car les initramfs-tools sont installés par défaut. Ensuite, pour créer un initramfs, j'exécute

  rpi ~ $ sudo update-initramfs -c -k $ (uname -r)  

et cela fonctionne comme un charme. Vous devez également le faire pour générer les premiers initramfs . Il en produit un par exemple /boot/initrd.img-4.14.71-v7+ . À partir de maintenant, vous pouvez simplement mettre à jour avec:

  rpi ~ $ sudo update-initramfs -uln: échec de la création du lien dur '/ boot / initrd. img-4.14.71-v7 + .dpkg-bak '= >' /boot/initrd.img-4.14.71-v7+ ': Opération non autoriséeupdate-initramfs: Génération de /boot/initrd.img-4.14.71-v7+ 

Comme vous le voyez, vous recevrez un avertissement (ce n'est pas une erreur) de ln . La partition de démarrage a un système de fichiers gros qui ne prend pas en charge les liens, mais cela n'a pas d'importance. Le seul problème est qu'il a besoin d'une entrée dans /boot/config.txt comme

initramfs initrd.img-4.14.71-v7 + (sans signe égal)

Sinon, le chargeur de démarrage ne peut pas trouver le disque mémoire et le démarrage échoue.

Avec Raspbian, nous avons également deux images de noyau, par exemple /boot/initrd.img-4.14.71 et /boot/initrd.img-4.14.71-v7+ et par défaut, update-initramfs génère un disque ram d'initialisation pour chaque noyau mais qui ne rentrera pas dans l'espace limité de la partition de démarrage. Nous devons donc également nous assurer que nous ne générons qu'un initramfs pour le noyau en cours d'exécution.

La gestion de initramfs se fait avec le script /etc/kernel/postinst.d/ outils-initramfs . Nous devons modifier ce script comme suit. Mais avant de déplacer le script d'origine vers un emplacement de sauvegarde:

  rpi ~ $ sudo mv /etc/kernel/postinst.d/initramfs-tools ~  

Ensuite, créez un fichier

  rpi ~ $ sudo editor /etc/kernel/postinst.d/rpi- initramfs-tools  

avec ce contenu:

  #! / bin / bash -e # Les variables d'environnement sont définies par l'appelant scriptversion = "$ 1" bootopt = "" commande -v update-initramfs > / dev / null 2>&1 || exit 0 # le passage de la version du noyau est requisif [-z "$ {version}"]; then echo >&2 "W: initramfs-tools: $ {DPKG_MAINTSCRIPT_PACKAGE: -kernel package} n'a pas passé de numéro de version" exit 2fi # exit si le noyau n'a pas besoin d'un initramfsif ["$ INITRD" = 'Non']; puis # effacez les entrées initramfs dans /boot/config.txt / bin / sed -i '/ ^ initramfs / d' /boot/config.txt exit 0fi # il n'y a que deux types de noyau: avec et sans suffixe "-v7 +" ou "-v8 +" currentversion = "$ (uname -r)" # get §currenttype à partir de $ currentversioncurrenttype = "<no currenttype>" echo $ currentversion | grep -Pq '^ \ d + \. \ d + \. \ d + \ + $' [$? -eq 0] && currenttype = "+" echo $ currentversion | grep -Pq '^ \ d + \. \ d + \. \ d + -v [78] \ + $' [$? -eq 0] && currenttype = "$ {currentversion # * -}" # get $ newtype à partir de $ version
newtype = "<no newtype>" echo $ version | grep -Pq '^ \ d + \. \ d + \. \ d + \ + $' [$? -eq 0] && newtype = "+" echo $ version | grep -Pq '^ \ d + \. \ d + \. \ d + -v [78] \ + $' [$? -eq 0] && newtype = "$ {version # * -}" # nous ne faisons rien si le nouveau noyau n'est pas pour le même type de noyau alors le currentif ["$ newtype"! = "$ currenttype"]; puis exit 0fi # le nom de fichier absolu de l'image du noyau peut être passé comme second argument; # crée le fichier initrd dans le même répertoireif [-n "$ 2"]; then bootdir = $ (dirname "$ 2") bootopt = "- b $ {bootdir}" fi # éviter d'exécuter plusieurs fois si [-n "$ DEB_MAINT_PARAMS"]; puis eval set - "$ DEB_MAINT_PARAMS" if [-z "$ 1"] || ["$ 1"! = "Configurer"]; puis quittez 0 fifi # nous allons bien - créez des initramfs. la mise à jour s'exécute do_bootloaderINITRAMFS_TOOLS_KERNEL_HOOK = 1 update-initramfs -c -t -k "$ {version}" $ {bootopt} >&2 # supprimer les entrées initramfs dans /boot/config.txt/bin/sed -i '/ ^ initramfs / d' boot / config.txt # insérer l'entrée initramfs dans /boot/config.txtINITRD_ENTRY="initramfs initrd.img - $ {version} "echo >&2 $ (nom de base" $ 0 "): insérer \" $ INITRD_ENTRY "" \ 'dans / boot /config.txt/bin/sed -i "1i $ INITRD_ENTRY" /boot/config.txt

Rendre le script exécutable:

  rpi ~ $ sudo chmod 755 /etc/kernel/postinst.d/rpi-initramfs-tools

Les extensions dans le script garantissent qu'un initramfs est uniquement créé pour le noyau en cours d'exécution et qu'il est géré une entrée dans /boot/config.txt . Si vous aimez voir les changements, vous pouvez le faire avec diff --ignore-tab-expansion ~ / initramfs-tools /etc/kernel/postinst.d/rpi-initramfs-tools.

Pour les mises à jour manuelles, nous créons:

  rpi ~ $ sudo editor / usr / local / sbin / update-rpi-initramfs  

avec ce contenu:

  #! / bin / bash # Ce script appelle default update-initramfs # puis insère une entrée 'initramfs' dans /boot/config.txt si nécessaire # devrait retour par exemple "update-initramfs: Génération de /boot/initrd.img-4.14.79-v7+"# ou" update-initramfs: Suppression de /boot/initrd.img-4.14.71-v7+"MSG=$(/usr/sbin/update -initramfs "$ @") RETCODE = $? echo $ MSGif [[$ RETCODE -ne 0]]; puis echo >&2 ATTENTION! Vérifiez l'entrée \ 'initramfs \' dans /boot/config.txt exit "$ RETCODE" fiCMP = "update-initramfs: Suppression *" if [[$ MSG == $ CMP]]; puis # supprimer les entrées initramfs dans /boot/config.txt / bin / sed -i '/ ^ initramfs / d' /boot/config.txt echo $ (basename "$ 0"): supprimé toutes les entrées \ 'initramfs \' de / boot / config.txt exit 0fiCMP = "update-initramfs: Generating *" if [[$ MSG == $ CMP]]; puis # supprimez les entrées initramfs dans /boot/config.txt / bin / sed -i '/ ^ initramfs / d' /boot/config.txt # exit si le noyau n'a pas besoin d'une source initramfs / etc / default / raspberrypi-kernel si ["$ {INITRD ,,}"! = 'Oui']; then echo $ (basename "$ 0"): pas d'entrée dans /boot/config.txt \ (voir INITRD dans / etc / default / raspberrypi-kernel \) exit 0 fi # insérer l'entrée initramfs dans /boot/config.txt VERSION = $ (basename "$ MSG") INITRD_ENTRY = "initramfs $ VERSION" echo $ (basename "$ 0"): insérez \ '"$ INITRD_ENTRY" \' dans /boot/config.txt / bin / sed -i "1i $ INITRD_ENTRY "/boot/config.txt exit 0fiecho >&2 ATTENTION! Vérifiez l'entrée 'initramfs' dans /boot/config.txtexit 1  

Définissez les autorisations:

  rpi ~ $ sudo chmod 755 / usr / local / sbin / update-rpi-initramfs  

À partir de maintenant, vous ne devriez utiliser que update-rpi-initramfs au lieu de update-initramfs , par exemple:

  rpi ~ $ sudo update-rpi-initramfs -u  

Cela garantit que vous avez toujours la bonne entrée dans /boot/config.txt .


Références:
[1] Scripts et hooks du responsable du package

Un nouvel utilisateur a eu une modification à ce sujet: * "Suppression de l'option -e de bashshenbang sinon le script se terminera avec le code d'erreur 1 sur 'echo $ currentversion | grep ...'" *. Je suppose que c'était votre intention et j'ai rejeté la modification, même si je n'ai pas réellement vérifié la logique.
@goldilocks Vous avez bien fait les choses. Le script doit échouer immédiatement lorsqu'une erreur se produit. Mais je ne sais toujours pas si cela peut être un bug. Je vais y jeter un œil. À propos: la réponse nécessite un examen complet.
Guenther Brunthaler
2019-07-03 22:19:45 UTC
view on stackexchange narkive permalink

Je peux proposer une solution alternative.

Au lieu de renommer l'image initramfs et de modifier les fichiers /etc/kernel/postinst.d/* existants, j'ai ajouté un hook initramfs qui modifie / boot / config.txt pour qu'il charge les initramfs avec son nom actuel.

Par conséquent, il n'est plus nécessaire de renommer les initramfs après la création, et il peut utiliser le nom standard choisi par les scripts de génération d'initramfs (c.-à-d. initrd.img- $ KERNELRELEASE).

Le script est personnalisable en définissant des variables pour tous les composants de nom de chemin importants à son début, de sorte que tous les paramètres personnalisables se trouvent au même endroit.

Le script évite également de mettre à jour config.txt s'il contient déjà le nom actuel de l'image initramfs réelle, ce qui économise un peu la durée de vie de votre carte SD.

Avant d'installer le hook, assurez-vous que votre / boot / config.txt contient la ligne que le hook tente de mettre à jour.

Cette ligne doit avoir un format comme le dernier dans la section suivante de mon con fig.txt:

  # Important: Cette valeur sera mise à jour par les scripts de génération initramfs. ## Syntaxe spéciale: ne pas utiliser "=" pour l'affectation ici.initramfs initrd.img-4.19.42 -v7 + followkernel  

J'ai nommé le script hook

/ etc / initramfs-tools / hooks / update_initrd_ref_qaumv1g34z54324pbel831evd

qui contient un UUID à la fin de son nom, il n'y a donc aucun risque de collision de noms avec les scripts existants ou futurs du même nom. Cependant, le nom n'a pas vraiment d'importance; n'hésitez pas à le renommer tant que vous le laissez dans le même répertoire.

Et voici le contenu de ce script:

  #! / bin / sh -e # Mettre à jour la référence à $ INITRD dans $ BOOTCFG, ce qui oblige le noyau à utiliser le nouveau # initrd après le prochain redémarrage.BOOTLDR_DIR = / bootBOOTCFG = $ BOOTLDR_DIR / config.txtINITRD_PFX = initrd.img-INITRD = $ INITRD_P $ 1 dans les prérequis) echo; exitesacFROM = "^ * \\ (initramfs \\) \\ + $ INITRD_PFX. \\ + \\ + \\ (followkernel \\) * \ $" INTO = "\\ 1 $ INITRD \\ 2"
T = `umask 077 && mktemp --tmpdir genramfs_XXXXXXXXXX.tmp`trap" rm - \ "$ T \" "0sed" s / $ FROM / $ INTO / "" $ BOOTCFG ">" $ T "Fichier de mise à jour uniquement si nécessaire, si! cmp -s "$ BOOTCFG" "$ T" puis cat "$ T" > "$ BOOTCFG" fi  

Notez qu'il s'agit d'un script, vous devez donc

  $ chmod + x / etc / initramfs-tools / hooks / update_initrd_ref_qaumv1g34z54324pbel831evd  

après sa création.

C'est en fait tout ce qu'il y a à faire - lancez

  $ update-initramfs -u  

comme d'habitude, et le contenu de /boot/config.txt devrait "automatiquement" correspondre au nom de votre /boot/initrd.img-* fichier.

Merci pour la suggestion. Je vais le tester en détail. Je viens juste d'y jeter un coup d'œil. Ce script sera-t-il déclenché automatiquement sur les mises à jour du noyau comme sur Debian par défaut?
@Ingo Oui, ça va / fait.
Tant que vous avez installé initramfs-tools.
Andrea Florio
2020-06-03 13:50:52 UTC
view on stackexchange narkive permalink

le script appelé lors de l'installation du noyau doit être légèrement édité car sinon il se terminera avec le code d'erreur 1 si grep ne correspond pas

  #! / bin / sh -e # Les variables d'environnement sont défini par la commande appelante scriptversion = "$ 1" bootopt = "" -v update-initramfs > / dev / null 2>&1 || exit 0 # le passage de la version du noyau est requisif [-z "$ {version}"]; then echo >&2 "W: initramfs-tools: $ {DPKG_MAINTSCRIPT_PACKAGE: -kernel package} n'a pas passé de numéro de version" exit 2fi # exit si le noyau n'a pas besoin d'un initramfsif ["$ INITRD" = 'Non']; puis # effacez les entrées initramfs dans /boot/config.txt / bin / sed -i '/ ^ initramfs / d' /boot/config.txt exit 0fi # il n'y a que deux types de noyau: avec et sans suffixe "-v7 +" ou "-v8 +" currentversion = "$ (uname -r)" # get §currenttype à partir de $ currentversioncurrenttype = "<no currenttype>" if [`echo $ currentversion | grep -P '^ \ d + \. \ d + \. \ d + \ + $' ']; puis [$? -eq 0] && currenttype = "+" else [`echo $ currentversion | grep -P '^ \ d + \. \ d + \. \ d + -v [78] l? \ + $' ']; [$? -eq 0] && currenttype = "$ {currentversion # * -}" fi # get $ newtype from $ versionnewtype = "<no newtype>" if [`echo $ version | grep -P '^ \ d + \. \ d + \. \ d + \ + $' `]; puis [$? -eq 0] && newtype = "+" else [`echo $ version | grep -P '^ \ d + \. \ d + \. \ d + -v [78] l? \ + $' ']; [$? -eq 0] && newtype = "$ {version # * -}" fi # nous ne faisons rien si le nouveau noyau n'est pas pour le même type de noyau alors le currentif ["$ newtype"! = "$ currenttype"]; puis exit 0fi # le nom de fichier absolu de l'image du noyau peut être passé comme second argument; # crée le fichier initrd dans le même répertoireif [-n "$ 2"]; then bootdir = $ (dirname "$ 2") bootopt = "- b $ {bootdir}" fi # éviter d'exécuter plusieurs fois si [-n "$ DEB_MAINT_PARAMS"]; puis ensemble d'évaluation - "$ DEB_MAINT_PARAMS"
si [-z "$ 1"] || ["$ 1"! = "Configurer"]; puis quittez 0 fifi # nous allons bien - créez des initramfs. la mise à jour s'exécute do_bootloaderINITRAMFS_TOOLS_KERNEL_HOOK = 1 update-initramfs -c -k "$ {version}" $ {bootopt} >&2 # supprimer les entrées initramfs dans /boot/config.txt/bin/sed -i '/ ^ initramfs / d' / boot / config.txt # insérer l'entrée initramfs dans /boot/config.txtINITRD_ENTRY="initramfs initrd.img - $ {version} followkernel "echo >&2 $ (nom de base" $ 0 "): insérer \ '" $ INITRD_ENTRY "\' dans / boot / config.txt / bin / sed -i "1i $ INITRD_ENTRY" /boot/config.txt  
Roger Jones
2019-01-14 17:39:40 UTC
view on stackexchange narkive permalink

Je n'ai pas testé cela, mais j'ai utilisé une méthode similaire pour ajouter des modules overlayfs et des scripts personnalisés aux initramfs pour activer l'opération RO. Si tout ce que vous voulez, c'est ajouter les modules LVM aux initramfs , je pense que tout ce que vous avez à faire est de:

  1. Ajoutez les modules que vous souhaitez inclure à /etc/initramfs-tools/modules.
  2. Ajoutez tous les scripts de support que vous devez exécuter pendant le démarrage dans '/ etc / initramfs-tools / scripts / ...'.
  3. Exécutez mkinitramfs -o / boot / initrd pour construire le initramfs
  4. Ajoutez initramfs initrd followkernel à votre /boot/config.txt pour l'activer.
  5. Redémarrer.

MODIFIER : comme Ingo l'a souligné dans les commentaires cette méthode ne recompile pas automatiquement les initramfs dans le cadre des mises à jour du système. Vous devrez réexécuter manuellement mkinitramfs -o / boot / initrd pour compiler une nouvelle image avec, par exemple, un nouveau module LVM pour correspondre à un noyau nouvellement installé. Donc, peut ne pas convenir à ce dont vous avez besoin.

Salut * Roger *, merci beaucoup pour vos commentaires. `J'utilise un initramfs depuis longtemps. [..] Mais c'est un peu dangereux car la mise à jour automatique d'un initramfs n'est pas prise en charge par Raspbian.` Plus de détails sur ma motivation pour faire cette mise à jour déclenchée, vous pouvez lire sur [Initramfs personnalisé] (https: //raspberrypi.stackexchange .com / a / 89914/79866). L'ajout de scripts de support dans `etc / initramfs-tools / scripts /` ne déclenche pas `update-initramfs` sur les mises à jour du noyau.
Si l'option `followkernel` est à quoi cela ressemble, ce serait un indice très utile pour simplifier mes scripts. Je vais regarder. Btw. J'utilise aussi `overlayfs` pour [Comment puis-je réinitialiser le système d'exploitation à chaque démarrage?] (Https://raspberrypi.stackexchange.com/a/85569/79866) mais je n'ai pas besoin d'un` initframfs` pour cela parce que `overlayfs` fait partie du noyau.
@Ingo C'est un commentaire juste sur cette méthode qui ne reconstruit pas automatiquement les `initramfs`. Ce n'était pas une considération pour ce que nous faisions car l'image finale du disque était plus ou moins statique une fois gravée sur la carte SD (nous ne nous attendions pas à ce que nos utilisateurs exécutent `apt-get`). Je vais modifier ma réponse pour clarifier ce point. Je ne savais pas que `unionfs` était dans le noyau de base mais a fait un usage intensif des scripts` initramfs` de toute façon pour retarder le démarrage pendant qu'un UPS se chargeait et ainsi de suite.
J'ai testé `initramfs initrd followkernel`. Cela n'a aucun effet. Le chargeur de démarrage n'utilise pas d'initramfs si initrd ne correspond pas exactement au nom dans `/ boot /`, par exemple «initrd.img-4.14.79-v7 +». J'ai envisagé de renommer l'initrd en un nom générique mais je n'ai aucun contrôle sur la version de la tne. Ne sais pas maintenant ce qui est mieux ...
@ingo Désolé, vous n'avez pas lu correctement votre réponse et vous utilisez déjà `sed` pour éditer` config.txt`. Je crois que `initramfs-tools` exporte la version en tant que variable, pouvez-vous modifier votre commande` sed` pour changer la ligne `initramfs` pour contenir la nouvelle version à la place? Quelque chose comme `sed -i" s / ^ initramfs \\ initrd. * / Initramfs \\ initrd.img - $ {version} / "/ boot / config.txt`? http://manpages.ubuntu.com/manpages/xenial/man8/initramfs-tools.8.html
@Ingo Je ne veux pas ajouter une suggestion sur l'exécution de `sed` depuis le répertoire` / etc / initramfs-tools / hooks / `pour éditer` config.txt` donc cela fait partie de la compilation plutôt que de la post-installation. Il me semble que cela devrait faire partie de la compilation (pour que `mkinitramfs` fonctionne aussi) mais il n'y a pas de moyen évident de le faire en toute sécurité dans l'environnement initramfs-tools.
akc42
2019-09-22 18:20:14 UTC
view on stackexchange narkive permalink

J'ai utilisé une solution différente, en ajoutant un hook dans le répertoire /etc/kernel/postinst.d . Cela fonctionne depuis un certain temps, mais je suis sur le point d'apporter une modification minuscule que je vais inclure ici et qui n'a pas été testée car je veux inclure la possibilité d'exécuter le noyau v8. J'ai donc ajouté ce script sous le nom /etc/kernel/postinst.d/rebuild

  #! / Bin / sh -e # Rebuild initramfs {7,8} .img après la mise à jour du noyau pour inclure les nouveaux modules du noyau. ## Quitter si la reconstruction ne peut pas être effectuée ou n'est pas nécessaire. [-x / usr / sbin / mkinitramfs] || exit 0 # Quitter si vous ne construisez pas le noyau pour la version matérielle de ce Raspberry Pi (supposons armv7l ou aarch64) .version = "$ 1" case "$ {version}" in * -v7 +) arch = 7 ;; * -v8 +) arch = 8 ;; *) exit 0esac [-f /boot/initramfs$arch.img] && lsinitramfs /boot/initramfs$arch.img | grep -q "/ $ version $" && exit 0 # Déjà dans initramfs. # Rebuild.mkinitramfs -o /boot/initramfs$arch.img "$ version"  

le rendant exécutable. Je ne touche pas du tout au fichier / etc / default / raspberrypi-kernel .

Je modifie /boot/config.txt pour soit inclure initramfs initramfs7.img followkernel ou initramfs initramfs8.img followkernel et arm_64bit = 1 . Cela ne me dérange pas de faire cette petite distinction que je pense nécessaire si souvent que je peux annuler l'indicateur arm_64bit si je le souhaite. C'est seulement



Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 4.0 sous laquelle il est distribué.
Loading...