Frage:
Wie kann ich eine Init-Ramdisk (initramfs) zum Booten von Raspberry Pi verwenden?
Ingo
2019-01-03 01:55:46 UTC
view on stackexchange narkive permalink

Ich muss den Treiber beim frühen Booten laden. Für die Entwicklung verwende ich LVM (Logical Volume Manager), damit ich Test-Setups aus einem Snapshot problemlos auf das Standard-Image zurücksetzen kann. Dazu muss ich den lvm-Treiber laden, bevor ich auf die Root-Partition zugreifen kann. Dies geschieht mit einer Init-Ramdisk (initrd oder initramfs). Dies ist auch gut, um benutzerdefinierten Kernel zu unterstützen. Im Gegensatz zu Debian unterstützt Raspbian jedoch keine sofort einsatzbereiten Initramfs. Wie kann ich eine Init-Ramdisk verwenden?

Fünf antworten:
Ingo
2019-01-03 01:55:46 UTC
view on stackexchange narkive permalink

Ich habe festgestellt, dass es ein Setup in

  gibt. rpi ~ $ cat / etc / default / raspberrypi-kernel # Standardeinstellungen für raspberrypi-kernel # Kommentieren Sie die folgende Zeile aus, um die Generierung von # /boot/initrd.img-KVER-Dateien zu aktivieren (erfordert initramfs-tools). # INITRD = Ja # Kommentieren Sie die folgende Zeile aus, um die Generierung von # /boot/initrd(7).img-Dateien zu aktivieren ( erfordert rpi-initramfs-tools) # RPI_INITRD = Ja  

Die Kommentare dort sind die einzige Dokumentation, die ich gefunden habe. Insbesondere kann ich nichts über rpi-initramfs-tools finden. Sie sind einfach nicht verfügbar. Deshalb habe ich mit INITRD = Yes getestet, indem ich es auskommentiert habe, da initramfs-tools standardmäßig installiert sind. Um dann ein Initramfs zu erstellen, führe ich

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

und es funktioniert wie ein Zauber. Sie müssen dies auch tun, um das erste initramfs zu generieren. Es wird beispielsweise /boot/initrd.img-4.14.71-v7+ erstellt. Von nun an können Sie einfach aktualisieren mit:

  rpi ~ $ sudo update-initramfs -uln: Hardlink '/ boot / initrd konnte nicht erstellt werden. img-4.14.71-v7 + .dpkg-bak '= >' /boot/initrd.img-4.14.71-v7+ ': Vorgang nicht zulässigupdate-initramfs: Generieren von /boot/initrd.img-4.14.71-v7+ 

Wie Sie sehen, erhalten Sie eine Warnung (es ist kein Fehler) von ln . Die Boot-Partition verfügt über ein fettes Dateisystem, das keine Links unterstützt, aber keine Rolle spielt. Das einzige Problem ist, dass ein Eintrag in /boot/config.txt wie

initramfs initrd.img-4.14.71-v7 + (ohne) erforderlich ist Gleichheitszeichen)

Andernfalls kann der Bootloader die Ramdisk nicht finden und der Startvorgang schlägt fehl.

Mit Raspbian haben wir auch zwei Kernel-Images, zum Beispiel /boot/initrd.img-4.14.71 und /boot/initrd.img-4.14.71-v7+ und standardmäßig generiert update-initramfs für jeden Kernel eine init-RAM-Disk, die jedoch nicht auf den begrenzten Speicherplatz der Boot-Partition passt. Daher müssen wir auch sicherstellen, dass wir nur ein initramfs für den laufenden Kernel generieren.

Das Verwalten von initramfs erfolgt mit dem Skript /etc/kernel/postinst.d/ initramfs-tools . Wir müssen dieses Skript wie folgt ändern. Bevor Sie jedoch das ursprüngliche Skript an einen sicheren Ort verschieben:

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

Erstellen Sie dann eine Datei

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

mit folgendem Inhalt:

  #! / bin / bash -e # Umgebungsvariablen werden festgelegt durch den aufrufenden Befehl scriptversion = "$ 1" bootopt = "" -v update-initramfs > / dev / null 2>&1 || exit 0 # das Übergeben der Kernel-Version ist erforderlich, wenn [-z "$ {version}"]; dann echo >&2 "W: initramfs-tools: $ {DPKG_MAINTSCRIPT_PACKAGE: -kernel package} hat keine Versionsnummer übergeben" exit 2fi # exit, wenn der Kernel kein initramfsif benötigt ["$ INITRD" = 'No']; dann # lösche initramfs Einträge in /boot/config.txt / bin / sed -i '/ ^ initramfs / d' /boot/config.txt exit 0fi # es gibt nur zwei Kerneltypen: mit und ohne Postfix "-v7 +" oder "-v8 +" currentversion = "$ (uname -r)" # get §currenttype from $ 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 # * -}" # $ newtype von $ version abrufen
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 # * -}" # wir tun nichts, wenn der neue Kernel nicht für denselben Kerneltyp ist, dann der currentif ["$ newtype"! = "$ currenttype"]; Beenden Sie dann 0fi. # Der absolute Dateiname des Kernel-Images kann als zweites Argument übergeben werden. # Erstellen Sie die Initrd im selben Verzeichnis, wenn [-n "$ 2"]; dann bootdir = $ (dirname "$ 2") bootopt = "- b $ {bootdir}" fi # mehrere Male vermeiden, wenn [-n "$ DEB_MAINT_PARAMS"]; dann eval set - "$ DEB_MAINT_PARAMS" wenn [-z "$ 1"] || ["$ 1"! = "Configure"]; dann beende 0 fifi # wir sind gut - erstelle initramfs. Das Update wird ausgeführt. do_bootloaderINITRAMFS_TOOLS_KERNEL_HOOK = 1 update-initramfs -c -t -k "$ {version}" $ {bootopt} >&2 # Initramfs-Einträge in /boot/config.txt/bin/sed -i '/ ^ initramfs / d /' löschen boot / config.txt # füge den initramfs-Eintrag in /boot/config.txtINITRD_ENTRY="initramfs initrd.img ein - $ {version} "echo >&2 $ (Basisname" $ ​​0 "): füge \ '" $ INITRD_ENTRY "\' in / boot ein /config.txt/bin/sed -i "1i $ INITRD_ENTRY" /boot/config.txt 

Machen Sie das Skript ausführbar:

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

Die Erweiterungen im Skript stellen sicher, dass nur ein Initramfs erstellt wird für den aktuell laufenden Kernel und dass ein Eintrag in /boot/config.txt verwaltet wird. Wenn Sie die Änderungen sehen möchten, können Sie dies mit diff --ignore-tab-extension ~ / initramfs-tools /etc/kernel/postinst.d/rpi-initramfs-tools tun.

Für manuelle Updates erstellen wir:

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

mit folgendem Inhalt:

  #! / bin / bash # Dieses Skript ruft das Standard-Update-initramfs # auf und fügt bei Bedarf einen 'initramfs'-Eintrag in /boot/config.txt ein zB zurück "update-initramfs: Generieren von /boot/initrd.img-4.14.79-v7+"# oder" update-initramfs: Löschen von /boot/initrd.img-4.14.71-v7+"MSG=$(/usr/sbin/update -initramfs "$ @") RETCODE = $? echo $ MSGif [[$ RETCODE -ne 0]]; dann echo >&2 ACHTUNG! Überprüfen Sie den Eintrag \ 'initramfs \' in /boot/config.txt. Beenden Sie "$ RETCODE" fiCMP = "update-initramfs: Löschen *", wenn [[$ MSG == $ CMP]]; dann # initramfs-Einträge in /boot/config.txt / bin / sed -i '/ ^ initramfs / d' /boot/config.txt löschen echo $ (Basisname "$ 0"): alle \ 'initramfs \' Einträge aus / gelöscht boot / config.txt exit 0fiCMP = "update-initramfs: Generating *" if [[$ MSG == $ CMP]]; dann # initramfs-Einträge in /boot/config.txt / bin / sed -i '/ ^ initramfs / d' /boot/config.txt löschen # beenden, wenn der Kernel keine initramfs-Quelle benötigt / etc / default / raspberrypi-kernel wenn ["$ {INITRD ,,}"! = 'Ja']; dann echo $ (Basisname "$ 0"): kein Eintrag in /boot/config.txt \ (siehe INITRD in / etc / default / raspberrypi-kernel \) exit 0 fi # initramfs-Eintrag in /boot/config.txt einfügen VERSION = $ (Basisname "$ MSG") INITRD_ENTRY = "initramfs $ VERSION" echo $ (Basisname "$ 0"): Fügen Sie \ "$ INITRD_ENTRY" \ / in /boot/config.txt / bin / sed -i "1i $ INITRD_ENTRY ein "/boot/config.txt exit 0fiecho >&2 ACHTUNG! Überprüfen Sie den Eintrag 'initramfs' in /boot/config.txtexit 1  

Berechtigungen festlegen:

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

Von nun an sollten Sie nur update-rpi-initramfs anstelle von verwenden update-initramfs , zum Beispiel:

  rpi ~ $ sudo update-rpi-initramfs -u  

Dies stellt sicher, dass Sie immer den richtigen Eintrag in /boot/config.txt .


Referenzen:
[1] Skripts und Hooks für die Paketverwaltung

Ein neuer Benutzer hatte eine Bearbeitung: * "Die Option -e wurde aus bashshenbang entfernt, andernfalls wird das Skript mit dem Fehlercode 1 auf 'echo $ currentversion | grep ...' beendet." Ich nehme an, dies war Ihre Absicht und lehnte die Bearbeitung ab, obwohl ich die Logik nicht wirklich überprüft habe.
@goldilocks Du hast es richtig gemacht. Das Skript schlägt sofort fehl, wenn ein Fehler auftritt. Aber ich bin mir immer noch nicht sicher, ob es ein Fehler sein könnte. Ich werde es mir ansehen. Übrigens: Die Antwort muss vollständig überprüft werden.
Guenther Brunthaler
2019-07-03 22:19:45 UTC
view on stackexchange narkive permalink

Ich kann eine alternative Lösung anbieten.

Anstatt das initramfs-Image umzubenennen und die vorhandenen Dateien /etc/kernel/postinst.d/* zu ändern, habe ich einen initramfs-Hook hinzugefügt, der / boot / ändert. config.txt, damit die Initramfs mit ihrem aktuellen Namen geladen werden.

Daher müssen die Initramfs nach der Erstellung nicht mehr umbenannt werden, und es kann der von den Initramfs-Generierungsskripten ausgewählte Standardname verwendet werden (dh initrd.img- $ KERNELRELEASE).

Das Skript kann angepasst werden, indem zu Beginn Variablen für alle wichtigen Pfadnamenskomponenten festgelegt werden, sodass sich alle anpassbaren Einstellungen an einer Stelle befinden.

Das Skript vermeidet auch das Aktualisieren von config.txt, wenn es bereits den aktuellen Namen des tatsächlichen initramfs-Images enthält, wodurch die Lebensdauer Ihrer SD-Karte ein wenig verkürzt wird.

Vergewissern Sie sich vor der Installation des Hooks, dass Sie / boot / config.txt enthält die Zeile, die der Hook zu aktualisieren versucht.

Diese Zeile muss ein Format wie das letzte im folgenden Abschnitt meiner Con haben fig.txt:

  # Wichtig: Dieser Wert wird durch Initramfs-Generierungsskripte aktualisiert. ## Spezielle Syntax: Verwenden Sie hier nicht "=" für die Zuweisung.initramfs initrd.img-4.19.42 -v7 + followkernel  

Ich habe das Hook-Skript

/ etc / initramfs-tools / hooks / update_initrd_ref_qaumv1g34z54324pbel831evd

benannt, das am Ende eine UUID enthält Daher besteht keine Gefahr von Namenskollisionen mit vorhandenen oder zukünftigen Skripten mit demselben Namen. Der Name spielt jedoch keine Rolle. Sie können es jederzeit umbenennen, solange Sie es im selben Verzeichnis belassen.

Und hier ist der Inhalt dieses Skripts:

  #! / bin / sh -e # Aktualisieren Sie den Verweis auf $ INITRD in $ BOOTCFG, sodass der Kernel nach dem nächsten Neustart die neue # initrd verwendet $ 1 in den Voraussetzungen) 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 "# Nur Datei wenn nötig.if! cmp -s "$ BOOTCFG" "$ T", dann cat "$ T" > "$ BOOTCFG" fi  

Beachten Sie, dass dies ein Skript ist, also müssen Sie

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

nach dem Erstellen.

Das ist eigentlich alles - Führen Sie

  $ update-initramfs -u  

wie gewohnt aus, und der Inhalt von /boot/config.txt sollte "automatisch" mit dem Namen Ihres Namens übereinstimmen Datei /boot/initrd.img-*.

Danke für den Vorschlag. Ich werde es im Detail testen. Hatte nur einen Blick darauf. Wird dieses Skript bei Kernel-Updates wie bei Debian standardmäßig automatisch ausgelöst?
@Ingo Ja, das wird / tut es.
Solange Sie initramfs-tools installiert haben.
Andrea Florio
2020-06-03 13:50:52 UTC
view on stackexchange narkive permalink

Das während der Kernelinstallation aufgerufene Skript muss leicht bearbeitet werden, da es sonst mit Fehlercode 1 beendet wird, wenn grep nicht übereinstimmt.

  #! / bin / sh -e # Umgebungsvariablen sind gesetzt durch den aufrufenden Befehl scriptversion = "$ 1" bootopt = "" -v update-initramfs > / dev / null 2>&1 || exit 0 # das Übergeben der Kernel-Version ist erforderlich, wenn [-z "$ {version}"]; dann echo >&2 "W: initramfs-tools: $ {DPKG_MAINTSCRIPT_PACKAGE: -kernel package} hat keine Versionsnummer übergeben" exit 2fi # exit, wenn der Kernel kein initramfsif benötigt ["$ INITRD" = 'No']; dann # lösche initramfs Einträge in /boot/config.txt / bin / sed -i '/ ^ initramfs / d' /boot/config.txt exit 0fi # es gibt nur zwei Kerneltypen: mit und ohne Postfix "-v7 +" oder "-v8 +" currentversion = "$ (uname -r)" # get §currenttype from $ currentversioncurrenttype = "<no currenttype>" if [`echo $ currentversion | grep -P '^ \ d + \. \ d + \. \ d + \ + $' `]; dann [$? -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 + \ + $' `]; dann [$? -eq 0] && newtype = "+" else [`echo $ version | grep -P '^ \ d + \. \ d + \. \ d + -v [78] l? \ + $' `]; [$? -eq 0] && newtype = "$ {version # * -}" fi # wir tun nichts, wenn der neue Kernel nicht für denselben Kerneltyp ist, dann der currentif ["$ newtype"! = "$ currenttype"]; Beenden Sie dann 0fi. # Der absolute Dateiname des Kernel-Images kann als zweites Argument übergeben werden. # Erstellen Sie die Initrd im selben Verzeichnis, wenn [-n "$ 2"]; dann bootdir = $ (dirname "$ 2") bootopt = "- b $ {bootdir}" fi # mehrere Male vermeiden, wenn [-n "$ DEB_MAINT_PARAMS"]; dann eval set - "$ DEB_MAINT_PARAMS"
if [-z "$ 1"] || ["$ 1"! = "Configure"]; dann beende 0 fifi # wir sind gut - erstelle initramfs. Das Update wird ausgeführt. do_bootloaderINITRAMFS_TOOLS_KERNEL_HOOK = 1 update-initramfs -c -k "$ {version}" $ {bootopt} >&2 # Initramfs-Einträge in /boot/config.txt/bin/sed -i '/ ^ initramfs / d' / boot / löschen config.txt # Initramfs-Eintrag in /boot/config.txtINITRD_ENTRY="initramfs initrd.img einfügen - $ {version} followkernel "echo >&2 $ (Basisname" $ ​​0 "): \" $ INITRD_ENTRY "\" in / boot / einfügen 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

Dies wurde nicht getestet, es wurde jedoch eine ähnliche Methode verwendet, um Overlayfs -Module und benutzerdefinierte Skripts zu den initramfs hinzuzufügen, um den RO-Betrieb zu aktivieren. Wenn Sie nur die LVM-Module zu den initramfs hinzufügen möchten, müssen Sie wahrscheinlich nur Folgendes tun:

  1. Fügen Sie die Module, die Sie einschließen möchten, zu hinzu /etc/initramfs-tools/modules.
  2. Fügen Sie alle Support-Skripte, die Sie beim Booten ausführen müssen, zu '/ etc / initramfs-tools / scripts / ...' hinzu.
  3. Führen Sie mkinitramfs -o / boot / initrd aus, um den initramfs
  4. zu erstellen. Fügen Sie initramfs initrd followkernel zu Ihrem /boot/config.txt , um es zu aktivieren.
  5. Neustart.
  6. ol>

    BEARBEITEN : Wie Ingo in ausgeführt hat Die Kommentare Diese Methode kompiliert die initramfs nicht automatisch als Teil von Systemaktualisierungen. Sie müssten mkinitramfs -o / boot / initrd manuell erneut ausführen, um ein neues Image mit beispielsweise einem neuen LVM-Modul zu kompilieren, das einem neu installierten Kernel entspricht. Ist möglicherweise nicht für das geeignet, was Sie benötigen.

Hallo * Roger *, vielen Dank für dein Feedback. `Ich benutze schon lange ein initramfs. [..] Aber es ist ein bisschen gefährlich, weil das automatische Aktualisieren eines Initramfs von Raspbian nicht unterstützt wird. `Weitere Details zu meiner Motivation, dieses ausgelöste Update durchzuführen, finden Sie unter [Benutzerdefiniertes Initramfs] (https: //raspberrypi.stackexchange) .com / a / 89914/79866). Das Hinzufügen von Support-Skripten in "etc / initramfs-tools / scripts /" löst bei Kernel-Updates kein "update-initramfs" aus.
Wenn die Option "followkernel" so ist, wie es aussieht, wäre dies ein sehr nützlicher Hinweis, um meine Skripte zu vereinfachen. Ich werde es mir ansehen. Übrigens. Ich verwende "Overlayfs" auch für [Wie kann ich das Betriebssystem bei jedem Start selbst zurücksetzen?] (Https://raspberrypi.stackexchange.com/a/85569/79866), aber ich benötige kein "Initframfs" dafür, weil `overlayfs` Teil des Kernels ist.
@Ingo Das ist ein fairer Kommentar zu dieser Methode, die die `initramfs` nicht automatisch neu erstellt. War keine Überlegung für das, was wir taten, da das endgültige Disk-Image nach dem Brennen auf die SD-Karte mehr oder weniger statisch war (wir würden nicht erwarten, dass unsere Benutzer "apt-get" ausführen). Ich werde meine Antwort ändern, um diesen Punkt zu klären. Wusste nicht, dass `unionfs` im Standardkernel war, nutzte aber trotzdem die` initramfs` -Skripte ausgiebig, um den Start zu verzögern, während eine USV aufgeladen wurde und so weiter.
Ich habe `initramfs initrd followkernel` getestet. Es hat keine Wirkung. Der Bootloader verwendet kein initramfs, wenn initrd nicht genau mit dem Namen in `/ boot /` übereinstimmt, z. `initrd.img-4.14.79-v7 +`. Ich habe überlegt, die initrd in einen generischen Namen umzubenennen, aber dann habe ich keine Kontrolle über die Version. K jetzt nicht, was besser ist ...
@ingo Entschuldigung, Sie haben Ihre Antwort nicht richtig gelesen und verwenden bereits "sed", um "config.txt" zu bearbeiten. Ich glaube, dass "initramfs-tools" die Version als Variable exportiert. Können Sie Ihren "sed" -Befehl bearbeiten, um die "initramfs" -Zeile so zu ändern, dass sie stattdessen die neue Version enthält? So etwas wie `sed -i" s / ^ initramfs \\ initrd. * / Initramfs \\ initrd.img - $ {version} / "/ boot / config.txt`? http://manpages.ubuntu.com/manpages/xenial/man8/initramfs-tools.8.html
@Ingo Ich möchte keinen Vorschlag zum Ausführen von `sed` aus dem Verzeichnis` / etc / initramfs-tools / hooks / `hinzufügen, um` config.txt` zu bearbeiten, sodass es eher Teil der Kompilierung als der Nachinstallation ist. Ich bin der Meinung, dass es Teil der Kompilierung sein sollte (damit `mkinitramfs` auch funktioniert), aber es gibt keine offensichtliche Möglichkeit, dies sicher in der initramfs-tools-Umgebung zu tun.
akc42
2019-09-22 18:20:14 UTC
view on stackexchange narkive permalink

Ich habe eine andere Lösung verwendet und einen Hook im Verzeichnis /etc/kernel/postinst.d hinzugefügt. Es hat eine Weile funktioniert, aber ich bin dabei, eine winzige Änderung vorzunehmen, die ich hier einfügen werde, die nicht getestet wurde, weil ich die Fähigkeit einschließen möchte, den v8-Kernel auszuführen. Also habe ich dieses Skript als /etc/kernel/postinst.d/rebuild

  #! / Bin / sh -e # Initramfs {7,8} .img neu erstellen Nach dem Kernel-Upgrade, um die Module des neuen Kernels einzuschließen. ## Beenden, wenn die Neuerstellung nicht durchgeführt werden kann oder nicht erforderlich ist. [-x / usr / sbin / mkinitramfs] || exit 0 # Beenden, wenn kein Kernel für die Hardwareversion dieses Raspberry Pi erstellt wird (angenommen armv7l oder aarch64) .version = "$ 1" case "$ {version}" in * -v7 +) arch = 7 ;; * -v8 +) arch = 8 ;; *) Beenden Sie 0esac [-f /boot/initramfs$arch.img] && lsinitramfs /boot/initramfs$arch.img | grep -q "/ $ version $" && exit 0 # Bereits in initramfs. # Rebuild.mkinitramfs -o /boot/initramfs$arch.img "$ version"  

macht es ausführbar. Ich berühre die Datei / etc / default / raspberrypi-kernel überhaupt nicht.

Ich bearbeite /boot/config.txt zu Enthalten Sie entweder initramfs initramfs7.img followkernel oder initramfs initramfs8.img followkernel und arm_64bit = 1 . Es macht mir nichts aus, diese kleine Unterscheidung zu treffen, die ich für so oft für notwendig halte, dass ich das Flag arm_64bit rückgängig machen kann, wenn ich möchte. Es nur



Diese Fragen und Antworten wurden automatisch aus der englischen Sprache übersetzt.Der ursprüngliche Inhalt ist auf stackexchange verfügbar. Wir danken ihm für die cc by-sa 4.0-Lizenz, unter der er vertrieben wird.
Loading...