[[Vorlage(getestet, bionic)]] {{{#!vorlage Wissen [:Terminal:] - Ein Terminal öffnen [:/ISO-Image/#Lesen-des-Inhalts-von-Image-Dateien:] - Den Inhalt eines ISO-Images lesen [:Editor:] - einen Editor öffnen [:Rechte/Dateimanager:] Rechte von Dateien anpassen }}} [[Inhaltsverzeichnis(2)]] {{{#!vorlage Warnung Der GRUB 2 Bootloader in der Version 2.0 (stable) ist weiter in der Entwicklung. Hinweise auf tatsächliche Gegebenheiten können daher noch fehlen bzw. nach einem Update nicht mehr zutreffen. Wesentliche Abweichungen sind gekennzeichnet und wenn erforderlich, auch beschrieben. }}} [[Bild(GRUB_2/grub-script.png, 54, left)]]GRUB 2 ermöglicht es, mit einfachen Mitteln das GRUB 2 Bootmenü an eigene Bedürfnisse und Wünsche anzupassen. Dazu kann man eigene Skripte erstellen, deren Syntax sich an der Standard-Shell [:Shell:] ausrichtet und im Verzeichnis '''/etc/grub.d''' abgelegt und dort lauffähig gemacht werden. = Erstellen eigener Menü-Einträge = Das Bearbeiten bzw. Verändern der Standardskripte im Verzeichnis '''/etc/grub.d''' sollte vermieden werden. Diese Veränderungen werden mit dem nächsten Update der GRUB-2-Pakete überschrieben! ==Generelles zur Skript-Erstellung== Die im Verzeichnis '''/etc/grub.d/''' abgelegten Skripte werden nicht vom Bootmanager GRUB zu dessen Laufzeit ausgeführt, sondern dienen nur zur Erstellung dessen Konfigurationsdatei '''grub.cfg'''. Die '''grub.cfg''' ist ihrerseits ein von GRUB zur Laufzeit ausgeführtes Skript (siehe [:GRUB_2/Grundlagen/#Systemstart:] ). Bei der Erstellung eines Skriptes für '''/etc/grub.d/''' muss der Programmierer daher beachten: * Alles, was das Skript auf die Standard-Ausgabe (`stdout`) schreibt, landet in der Datei '''grub.cfg''' und muss aus zulässigen Befehlen in der Skript-Sprache von GRUB bestehen. * Informationen, die während der Generierung der Datei '''grub.cfg''' den Bediener des Linux-Systems erreichen sollen, dürfen vom Skript nicht auf die Standardausgabe, sondern müssen auf die Fehlerausgabe (`stderr`) geschrieben werden. Beispiel: {{{echo "Hallo von ${0##*/}" >&2 }}} * Das Skript kann die in der '''/etc/default/grub''' und in den Dateien '''/etc/default/grub.d/*.cfg''' definierten Einstellungen verwenden. * Die Generierung der Datei '''grub.cfg''' erfolgt in der Regel mit dem Befehl [[Vorlage(Befehl, "sudo update-grub") ]] Zu Testzwecken eignet sich aber noch besser der Befehl [[Vorlage(Befehl, "sudo grub-mkconfig") ]] ohne irgendwelche Parameter, der die Änderungen einfach nur am Bildschirm ausgibt und noch nicht in die '''grub.cfg''' schreibt. Im Folgenden werden die für die meisten Situationen gängigen Menü-Einträge erklärt. Dabei handelt es sich lediglich um Beispiele, die anleiten sollen, eigene Skripte richtig zu erstellen. {{{#!vorlage Hinweis Die Beispiele und Entwürfe müssen an das jeweilige System angepasst werden - insbesondere die Datenträger- und Partitionsbezeichnungen sowie andere Parameter wie z.B. die [:UUID:]. }}} == Anlegen eines eigenen Skriptes == Zunächst muss ein eigenes Skript angelegt werden. Dazu legt man mit einen Editor [3] eine Datei mit dem Namensschema '''XX_EIGENES_SKRIPT''' vorzugsweise im eigenen [:Homeverzeichnis:] an. Dabei muss die Bezeichnung - wie unter [:GRUB_2/Konfiguration#Die-Abarbeitungs-Reihenfolge-der-Skripte:Konfiguation] von GRUB 2 dargestellt - den eigenen Bedürfnissen entsprechend angepasst werden. {{{#!vorlage Hinweis Eine Variable im eigenen Skript kann auf zwei Arten interpretiert werden: * Übernahme eines Werte aus der Datei '''/etc/default/grub''' in die '''/boot/grub/grub.cfg''', dann wird der z.B.: mit $`{GRUB_CMDLINE_LINUX_DEFAULT}` vorgegebene Inhalt (z.B.: `quiet splash`) direkt übernommen * Soll dagegen die Übernahme eines Werte erst beim Booten erfolgen, dann wird das mit einem vorangestelltem Rückstrich ( \ ), wie z.B.: bei `\${root}` in ein eigenes Skript eingetragen. }}} Nachdem das Skript inhaltlich den eigenen Vorstellungen entspricht, muss man diese Datei vor dem Kopieren mit den erforderlichen Rechten [4] versehen und die Ausführbarkeit einstellen. Jetzt kann man diese Datei im Terminal [1] mit: {{{#!vorlage Befehl sudo cp -f MEINE_DATEI /etc/grub.d/ }}} kopieren und sich im Terminal [1] mit: {{{#!vorlage Befehl sudo grub-mkconfig }}} das Ergebnis anzeigen lassen. = Allgemeiner Aufbau Menüeintrag = Das folgende Beispiel für ein Skript wurde abgeleitet aus einem Standard-Eintrag für den [:Recovery_Modus:]): == Allgemeines Beispiel == {{{#!code bash #! /bin/sh -e echo "Füge Eintrag für Lucid Lynx ein" >&2 cat << EOF menuentry "Ubuntu" --class ubuntu --class gnu-linux { recordfail savedefault insmod ext2 set root='(hd0,msdos3)' search --no-floppy --fs-uuid --set=root ae875d31-cc84-4349-95d7-01a82ad76d61 linux /vmlinuz root=UUID=ae875d31-cc84-4349-95d7-01a82ad76d61 ro ${GRUB_CMDLINE_LINUX_DEFAULT} echo Lade aktuellen Kernel von ${GRUB_DEVICE}... initrd /initrd.img echo Lade und Initiere RAM-Image von ${GRUB_DEVICE}... } EOF }}} === Erläuterungen === Es sind dabei die [:GRUB_2/Konfiguration#Festplatten-und-Partitions-Bezeichnungen: Festplatten- bzw. Partitions-Bezeichnung], die [:UUID:] und soweit eingesetzt, die [:Kernel:]-Bezeichnung an die jeweiligen Gegebenheiten anzupassen! {{{#!vorlage Tabelle <-2 rowclass="titel"; tablestyle="width: 95%";> Befehlszeilen in den Skripten +++ <: rowclass="kopf"; cellstyle="width: 70px;" > Zeile <:> Funktion +++ <^(>Zeile 1: Die erforderliche [:Shell/Bash-Skripting-Guide_für_Anfänger#Die-Shebang: Shebang] für jedes separate Skript im Verzeichnis '''/etc/grub.d/'''. +++ <^(>Zeile 3: Diese Zeile ist optional. Beim Updaten der Grub-Konfiguration mit `grub-mkconfig` bzw. `update-grub` im Terminal gibt diese Zeile eine Rückmeldung - im Beispiel `"Füge Eintrag für Lucid Lynx ein"` - so dass man überprüfen kann, ob das Skript berücksichtigt wurde. Der Text für die Rückmeldung kann dabei innerhalb der `""` beliebig festgelegt werden. +++ <^(>Zeile 5+17: `cat << EOF` und das abschließende `EOF` stellen den Bereich dar, der später der '''/boot/grub/grub.cfg''' hinzugefügt wird. Menü-Einträge müssen also innerhalb dieses Bereichs definiert werden. +++ <^(>Zeilen 6-16: Definieren den eigentliche Bereich für einen Menü-Eintrag. +++ <^(>Zeile 6: Der Menü-Eintrag wird eingeleitet durch `menuentry "Bezeichnung"`, danach später nicht mehr sichtbare interne Systemparameter wie `--class ubuntu` sowie mit dem Startzeichen `{` für die Menü-Sequenz. Die Bezeichnungen werden dabei für die __automatisch__ generierten Einträge von den gefundenen Kernel-Bezeichnungen abgeleitet (für eigene Skripte sind diese frei wählbar) und repräsentieren dann den Eintrag im Auswahlmenü. [[Vorlage(Experten,"Will man die automatisch generierte Bezeichnung `Ubuntu` auch auf das installierte Ubuntu-Derivat einstellen, dann kann man die Skripte unter [#Anzeige-in-der-Menuezeile Anzeige in der Menüzeile] verwenden.")]] +++ <^(> Zeile 7: Dieser Eintrag wird automatisch __nur__ für Kerneleinträge im Verzeichnis '''/boot''' erstellt. Damit wird vorsorglich ein Eintrag für die Datei '''/boot/grub/grubenv''' generiert, falls es bei dem nachfolgenden Auslesen Fehler geben sollte oder das System aus der GRUB-2-Commandline gestartet wurde (aufgerufen mit Taste [[Vorlage(Tasten, C)]] bzw. [[Vorlage(Tasten, E)]]). +++ <^(> Zeile 8: Hiermit wird der mittels Pfeiltaste [[Vorlage(Tasten, up)]] bzw. [[Vorlage(Tasten, down)]] im GRUB-Menü aktuell ausgewählte Eintrag mit seiner Bezeichnung (siehe Zeile 6) in der Datei '''/boot/grub/grubenv''' abgespeichert. [[Vorlage(Hinweis,"Dieser Eintrag wird bei einem `update-grub` __nur__ für Kerneleinträge im Verzeichnis '''/boot''' erstellt __und__ wenn die Option `GRUB_SAVEDEFAULLT=true` in der Datei '''/etc/default/grub''' aktiviert wurde. Diese Auswahl wird beim nächsten Booten __nur__ angeboten, sofern __auch__ die Option `GRUB_DEFAULT=saved` in der Datei '''/etc/default/grub''' entsprechend aktiviert wurde.")]] +++ <^(> Zeile 9: Gibt die Art der Formatierung des Datenträger an und veranlasst GRUB 2 die entsprechenden Treiber zu laden. Es muss für jeden erforderlichen Treiber eine Zeile / ein Eintrag vorgesehen werden - siehe dazu auch die Ausführungen [#LVM-und-RAID zu den Treibern]. +++ <^|2(>Zeile 10: `set root=` gibt die Partition an, auf der die Bootdateien des im Menü-Eintrag angegebenen Systems liegen. Siehe dazu auch [:GRUB_2/Konfiguration#Festplatten-und-Partitions-Bezeichnungen: Festplatten- und Partitions-Bezeichnungen]. +++ <^(> Je nach Erstellung der Partitionstabelle sind z.B. `(hd0,msdos3)`, `(hd0,gpt3)` einzusetzen. +++ <^|4>Zeile 11: Die Option `--no-floppy` unterbindet die Suche nach einem Floppy-Disk-Laufwerk. Statt `--no-floppy` kann auch die Kurzform `-n` gesetzt werden. +++ Der Eintrag `search --fs-uuid --set=root` sucht nach der angegebene [:UUID:] der Partition hinter `set=root`. Statt `--fs-uuid` kann auch die Kurzform `-u` gesetzt werden. +++ Ein Eintrag `search --label --set=root` sucht nach dem angegebenen [:Labels: Label] der Partition hinter `set=root`. Statt `--label` kann auch die Kurzform `-l` gesetzt werden. +++ Wird die Suche mit den vorgegebenen Parametern fündig, so überschreibt dieser Eintrag die Vorgabe aus der Zeile 10. Wird die angegebene Vorgabe nicht gefunden - z.B. weil die Partition zwischenzeitlich formatiert wurde - dann wird das `set root=` aus Zeile 10 angewendet. +++ <^(>Zeile 12: Diese Zeile gibt die Bezeichnung für den Kernel an, der geladen werden soll und wo sich dieser befindet (siehe auch nachfolgend die diversen Varianten). Der Eintrag der Kernel-Optionen erfolgt entsprechend der obigen Vorgaben, siehe [:GRUB_2/Konfiguration#Variable-fuer-Kernelzeilen: Variablen für Kernelzeilen]. Hier kann entweder der relative Pfad (wie im Beispiel) als auch der absolute Pfad mit relevantem Kernel angegeben werden. +++ <^(>Zeile 13+15: Diese Zeile wird __automatisch__ bei Menüeinträgen für den [:Recovery_Modus:] erstellt und nach der Auswahl angezeigt. Diese Anzeige kann auch für eigene Skripte angewendet werden. Der Zusatz `${GRUB_DEVICE}` fügt automatisch die relevante Partition in Form von `/dev/sda3` ein. +++ <^(>Zeile 14: Diese Zeile gibt die Bezeichnung für das Boot-Image an, das geladen werden soll und wo sich dieses befindet (siehe auch nachfolgend die diversen Varianten) und den Hinweis in Zeile 12. +++ <^(>Zeile 16: Hier befindet sich das abschließende `}` für den Menüeintrag. }}} = Ubuntu oder andere Linux-Distributionen starten = == Kernel-Images == Ein Kernel-Menü-Eintrag ist der Standard-Menü-Eintrag unter GRUB 2, um ein Linux-System zu booten. Dazu wird der Pfad zum entsprechenden Kernel-Image - der das Starten des Systems einleitet - angegeben. Grundsätzlich werden Kernel-Einträge automatisch über das Skript '''10_linux''' für die aktuelle Distribution und '''30_os_prober''' für andere auf dem Computer installierte Linux-Distributionen gesucht und erstellt. Sollte es notwendig sein, so kann man einen solchen Eintrag auch manuell erstellen. Beispiel: {{{#!code bash #! /bin/sh -e echo "Adding Saucy Salamander entry" >&2 cat << EOF menuentry "Ubuntu, mit Linux 3.11.0-15-generic" { insmod ext2 set root='(hd0,msdos3)' search --no-floppy --fs-uuid --set=root d3afdd1-045a-490f-b7ba-86c0c2d8c500 linux /boot/vmlinuz-3.11.0-15-generic root=UUID=d3afdd1-045a-490f-b7ba-86c0c2d8c500 ro quiet splash initrd /boot/initrd.img-3.11.0-15-generic } EOF }}} Liegt das Zielsystem auf einem externen Datenträger wie z.B. einer USB-HDD, so ist zu obigem Eintrag zusätzlich direkt unter der Zeile `menuentry` die Zeile 3 einzutragen: {{{#!code bash .... menuentry "Ubuntu, auf externer Festplatte" { insmod usb insmod ext2 .... }}} damit die folgenden Daten richtig ausgelesen werden können. Das externe Medium muss aber grundsätzlich vom BIOS erkannt und ausgelesen werden können. Insbesondere einige USB-3.0-Ports haben damit in diesem frühen Zeitpunkt noch Probleme. == Anzeige in der Menüzeile == Für Ubuntu wird aufgrund der System-ID als Anzeige im GRUB-Menü immer "Ubuntu" verwendet, auch wenn es sich z.B. um das Derivat "Lubuntu" handelt. Dieser Umstand ist für viele Benutzer unbefriedigend. Um diese Anzeige auf das wirkliche Derivat zu bringen, kann man nachfolgende Veränderungen vornehmen: === Derivate-Kennung aktivieren === Es ist in der '''/etc/default/grub''' folgende Änderung mit Rootrechten einzubringen: {{{ #GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian` GRUB_DISTRIBUTOR="Lubuntu" }}} Hier wurde als Ersatz für {*} Ubuntu beispielhaft {l} Lubuntu für die Anzeige im GRUB-Menü eingesetzt. === Basis für Umstellung der Anzeige=== In das Verzeichnis '''/etc/grub.d''' wird das folgende Skript ausführbar als '''00_add_custom_distributor''' abgelegt. Damit wird sichergestellt: * das bei einem Upgrade von [:GRUB_2:] * diese Änderung wieder übernommen wird * die angepasste Bezeichnung in den GRUB-Skripten Verwendung findet {{{#!code bash #!/bin/sh -e [ "$GRUB_DISTRIBUTOR" ] || exit; [ "$GRUB_DISTRIBUTOR" = "Ubuntu" ] && exit; echo "GRUB_DISTRIBUTOR in use = $GRUB_DISTRIBUTOR" >&2; for grub_script in /etc/grub.d/*;do grub_script=$(realpath $grub_script) if [ "$(file -b "$grub_script")" = "POSIX shell script, ASCII text executable" ] && [ "x$grub_script" != "x/etc/grub.d/00_add_custom_distributor" ]; then if grep -r 'Ubuntu|Kubuntu.*' $grub_script >/dev/null 2>&1; then sed -i s/Ubuntu\|Kubuntu.*\)/Ubuntu\|Kubuntu\|$GRUB_DISTRIBUTOR\)/g $grub_script >/dev/null 2>&1 fi fi done }}} Man testet dieses danach im Terminal [1] aus mit {{{#!vorlage Befehl sudo grub-mkconfig }}} und überprüft die dabei angezeigten Anzeigen unter dem jeweiligen `menuentry`, bevor man das mit {{{#!vorlage Befehl sudo update-grub }}} in sein System übernimmt. == LVM und RAID == Ein Fortschritt von GRUB 2 ist, dass die Informationen für ein Betriebssystem von einem [:Software-RAID: RAID-Verbund] oder [:LVM:] sowie eine Kombination aus beiden, __direkt__ ausgelesen werden kann. [[Vorlage(Warnung,"Die Funktion ''\"savedefault\"'' bzw. ''\"recordfail\"'' funktioniert zur Zeit weder auf einem RAID-Verbund (siehe [bug:560594:]), einem LVM-Dateisystem (siehe [bug:625234:]) noch beim [:Btrfs:]-Dateisystem!")]] === LVM-RAID-Skript === Ein Menüeintrag am Beispiel einer Kombination kann dann so aussehen: {{{#!code bash #! /bin/sh -e echo "Füge eigene Menü-Option Saucy Salamander ein" >&2 cat << EOF menuentry "Ubuntu, mit Linux 3.11.0-15-generic" { insmod raid insmod mdraid insmod lvm insmod ext2 set root='(vg_1-boot)' search --no-floppy --fs-uuid --set=root 11992cde-b1d9-4392-bcc4-13c2ce8702aa linux /vmlinuz-3.11.0-15-generic root=/dev/mapper/vg_1-root ro quiet splash initrd /initrd.img-3.11.0-15-generic } EOF }}} Relevant sind dabei die Zeilen, die mit `insmod` beginnen. Hier werden die Module für das RAID `raid`, `mdraid` und für das LVM benötigte Modul `lvm` geladen. Des Weiteren muss die Bezeichnung für das LVM-Device (hier im Beispiel `vg_1-boot` in Zeile 11 bzw. `vg_1-root` in Zeile 13) neben den anderen Daten an die eigenen Gegebenheiten angepasst werden! In der Regel werden die erforderlichen Module durch das Skript '''/etc/grub.d/10_linux''' bei einem `grub-mkconfig` bzw. `update-grub` automatisch ermittelt und eingesetzt. == Symlink zum Wurzelverzeichnis == Ein [wikipedia:Symbolische_Verknüpfung:symlink]-Menü-Eintrag startet wie der Kernel-Menü-Eintrag auch einen Linux Kernel. Dabei wird anstelle einer kompletten Pfad- und Kernel-Bezeichnung {{{#!code bash linux /boot/vmlinuz-2.6.32-25-generic root=UUID=41b9df5e-....-... initrd /boot/initrd.img-2.6.32-25-generic }}} der Pfad als Symlink zum Kernel angegeben. Dieser Symlink befindet sich direkt im Wurzelverzeichnis und verweist im folgenden Beispiel auf den jeweils aktuellen Kernel im Verzeichnis '''/boot'''. {{{#!code bash linux /vmlinuz root=UUID=41b9df5e-...-... initrd /initrd.img }}} {{{#!vorlage Experten Es ist zu beachten, dass der automatisch generierte Symlink im Wurzelverzeichnis bei einem Betriebssystem mit einem [:EFI_Bootmanagement:] den Einsprung für das `secure-boot` auf das Image '''vmlinuz-xxx-generic.efi.signed''' nicht berücksichtigt! Es muss __immer__ geprüft werden, ob dieser Symlink sowohl nach einem Kernelupdate als auch beim [:Kernel#Kernel-deinstallieren:Entfernen alter Kernel] richtig gesetzt wurden. Es können sich dabei diese symbolischen Links so verändern, dass ein Starten des Systems verhindert wird. }}} == Symlink zur Boot-Partition == Befindet sich das Verzeichnis '''/boot''' auf einer separaten Partition, so greift die Vorgehensweise unter [#Symlink-zum-Wurzelverzeichnis Symlink zum Wurzelverzeichnis] nicht. Dazu muss dann das folgende Skript (mit z.B. mit '''09_K_aktuell''' bezeichnet) zwischengeschaltet werden: {{{#!code bash #!/bin/sh -e # Hiermit wird bei einem 'update-grub' der aktuelle Kernel # intern auf eine einheitliche Form innerhalb '/boot' verlinkt. SETZE_LINK () { rm -f ${SUCHE_WAS}; list=$( for i in ${SUCHE_WAS}-* ; do echo -n "$i " ; done ) [ "x$list" = "x" ] && exit linux=$( version_find_latest $list ) ln -s "$linux" ${SUCHE_WAS} > /dev/null echo "Link für $linux eingefügt" >&2; } . /usr/lib/grub/grub-mkconfig_lib cd /boot; SUCHE_WAS="vmlinuz" && SETZE_LINK; SUCHE_WAS="initrd.img" && SETZE_LINK; }}} Nun wird nach jedem Kernelupdate bzw. nach der Eingabe in das Terminal von: [[Vorlage(Befehl,"sudo update-grub")]] ausschließlich der jeweils __aktuelle__ (höchste) Kernel als Symlink im Verzeichnis für die Images angeboten. {{{#!vorlage Experten Dieses Skript berücksichtigt auch die Belange eines [:EFI_Bootmanagement:] und setzt, sofern ein `secure-boot` erkannt wurde, den Symlink auf das aktuelle Image '''vmlinuz-xxx-generic.efi.signed'''. Das Skript kann somit generell für eine Korrektur des automatisch gesetzten [#Symlink-zur-Boot-Partition Symlink zur Boot-Partition] benutzt werden. }}} == Configfile == Mit einem configfile-Menü-Eintrag kann man GRUB 2 anweisen, die Menü-Konfiguration zur Laufzeit aus einer anderen Datei als der standardmäßigen '''/boot/grub/grub.cfg''' zu entnehmen. Das ist z.B. dann sinnvoll, wenn man eine weitere Distribution auf dem Computer installiert hat, die auch GRUB 2 als Bootloader einsetzt oder aber auch einfach nur für Experimente. Beispiel: {{{#!code bash #! /bin/sh -e echo "Adding Precise Testing menuentry" >&2 cat << EOF menuentry "Nachladen Precise grub.cfg von /dev/sdb1" { insmod ext2 set root='(hd1,1)' search --no-floppy --fs-uuid --set=root 11992cde-b1d9-4392-bcc4-13c2ce8702aa configfile /boot/grub/grub.cfg } EOF }}} Hier wird die '''/boot/grub/grub.cfg''' einer Installation eingelesen, die sich auf der ersten Partition der zweiten Festplatte im Computer befindet. Mit der [[Vorlage(Tasten,Esc)]]-Taste kann man wieder in das Menü zurück wechseln, von dem aus aufgerufen wurde. == Submenü einrichten == Man kann die Funktion [:GRUB_2/Konfiguration#Erscheinungsbild-Grubmenue:Submenü] auch für seine eigenen Zwecke benutzen. Um das zu realisieren, kann man verschiedene Wege beschreiten - wichtig ist nur, dass man die relevanten Menüpunkte (Skripte) zusammenfasst und vor diesen die Sequenz {{{#!code bash submenu 'Meine Menüsammlung' { }}} im ersten Skript einbringt und am Ende der Sammlung noch eine geschweifte Klammer hinter dem letzten Skript __zusätzlich__ anordnet. Oder man macht das z.B.: jeweils in einem Skript, dass dann in der Zählung entsprechend angelegt wird: * '''12A_submenu_start''' mit: {{{#!code bash #! /bin/bash -e cat << EOF submenu 'Meine Menüsammlung' { EOF }}} * '''13_... bis 16_...''' Skriptesammlung * '''19A_submenu_abschluss''' mit: {{{#!code bash #! /bin/bash -e cat << EOF } EOF }}} = Fremde Betriebssysteme (Windows) mittels chainloader laden = Der [wikipedia:Boot-Loader#Chain-Loader:chainloader]-Menü-Eintrag wird für Betriebssysteme genutzt deren Kernel GRUB 2 nicht direkt laden kann - in der Praxis also in aller Regel Windows. Dabei wird GRUB 2 angewiesen, das fremde System zu starten, indem es entweder den Partitions-Bootsektor der Partition des betreffenden Betriebssystems oder aber den [wikipedia:Master-Boot-Record: MBR] der Platte auf der das betreffende Betriebssystem installiert ist, lädt. Dabei muss man aber unterscheiden, wie das fremde Betriebssystem installiert wurde: * im ''"BIOS-Modus"'' * im ''"EFI-Modus"'' {{{#!vorlage Experten Eine Mischung aus beiden Modi ist nicht startfähig bzw. diese können sich nicht wechselseitig aufrufen. }}} == Beispiel BIOS-Modus == In der Regel wird das Windows bei der Installation von Ubuntu automatisch gefunden und der Menüeintrag richtig erstellt. Mit dem folgenden Skript kann man Probleme oder Besonderheiten umgehen, um Windows zu starten. Man muss als erstes ermitteln, auf welcher Partition sich der Bootmanager (die Datei '''bootmgr''') von Windows befindet. Das kann je nach Art der Installation von Windows auf der separaten Partition mit der Bezeichnung * ''"System-reserviert"'' oder auf einer normalen '''NTFS'''-Partition sein. Diese sei beispielhaft '''/dev/sda1'''. Mit dieser Information ermittelt man die [:UUID:] mit: [[Vorlage(Befehl,"sudo grub-probe -t fs_uuid -d /dev/sda1")]] Diese [:UUID:] wird nun in das folgende Skript in Zeile 7 übernommen: {{{#!code bash #! /bin/sh -e echo "Füge einen Starteintrag für Windows ein" >&2 cat << EOF menuentry "Microsoft Windows im BIOS-Modus starten" { insmod part_msdos insmod ntfs search --no-floppy --fs-uuid --set=root eaf815c4f8159045 parttool \${root} hidden- drivemap -s (hd0) \${root} chainloader +1 } EOF }}} {{{#!vorlage Experten Es ist darauf zu achten, dass in der Zeile 9 die Nummerierung von '''(hd0)''' sich auf den Datenträger bezieht, auf der sich GRUB 2 mit der '''../grub.cfg''' befindet. Herausfinden lässt sich das, indem man im GRUB-Menü mit [[Vorlage(Tasten,C)]] die `cmdline` aufruft und am Prompt * grub> `ls` eingibt. Aus den angezeigten Datenträgern muss man nun die richtige Zuordnung treffen (was manchmal nicht ganz einfach ist). Nachdem man mit [[Vorlage(Tasten,Esc)]] die `cmdline` verlassen und mit den Pfeiltasten den Windows-Eintrag ausgewählt hat, kann man diesen mit [[Vorlage(Tasten,E)]] zum Editieren aufrufen. Nach der Korrektur der `drivemap`-Zeile muss man nun mit der Taste [[Vorlage(Tasten,F10)]] den Bootvorgang starten. }}} == Beispiel EFI-Modus == [[Vorlage(Hinweis, "''\"fast-boot\"'' sowie ''\"secure-boot\"'' dürfen im Setup nicht aktiviert sein!")]] In der Regel wird ein EFI-Windows bei der Installation von Ubuntu (bis Version [:Raring_Ringtail:] (13.04)) nicht automatisch gefunden und der Menüeintrag fehlt deshalb im GRUB-Menü. Das ist kein [bug::], sondern konzeptionell so gewollt! Lässt sich das Windows aber über das EFI-Menü des Rechners starten, dann kann man das auch in das GRUB-Menü einbringen und von hier aus das Windows starten. Dabei ist es wichtig, dass das Ubuntu im EFI-Modus gestartet wurde, von dem aus das Windows aufgerufen werden soll! Dazu gibt man in ein Terminal [1] ein: [[Vorlage(Befehl,"sudo parted -l")]] und sucht in der Ausgabe unter * `Flags` nach * `EFI system partition` (oder einem sinngemäß vergleichbaren Eintrag) und überprüft das Vorhandensein einer EFI-Partition. Diese Partition wird zur Erstellung des folgenden Skriptes als Ziel verwendet und wird z.B. als '''29_windows''' lauffähig in das Verzeichnis '''/etc/grub.d''' abgelegt und sollte nach einen [[Vorlage(Befehl,"sudo update-grub")]] einen Eintag im GRUB-Menü zum Starten des Windows bereitstellen. {{{#!code bash #!/bin/bash # EFI-Partition suchen und auswerten if [ -f /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi ]; then EFI_UUID=$( grub-probe -t fs_uuid /boot/efi/EFI ) echo "Menüeintrag für Windows eingefügt" >&2 cat <&2 cat << EOF menuentry 'Precise Pangolin Live CD i386-ISO booten' { insmod part_msdos insmod ntfs insmod ext2 search -n -f --set=root ${GRUB_LOOPBACK_ISO_FILE} loopback loop ${GRUB_LOOPBACK_ISO_FILE} linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=${GRUB_LOOPBACK_ISO_FILE} \ ${GRUB_CMDLINE_LINUX_DEFAULT} ${GRUB_CMDLINE_LINUX} quiet splash -- initrd (loop)/casper/initrd.lz } EOF }}} Die Bezeichnung `loop` im obigen Beispiel als Identmerkmal ist frei wählbar, sollte aber keine Umlaute enthalten! Durch dieses Skript wird ein Menü-Eintrag generiert, der das mittels '''/PFAD_ZUM_ISO/ubuntu-xyz-i386.iso''' ausgewiesene ISO-Image auf den Festplatten sucht und als Live-CD bootet. Der '''/PFAD_ZUM_ISO/''' darf im übrigen nicht das Laufwerk enthalten, da die Zeile {{{ search -n -f --set=root ${GRUB_LOOPBACK_ISO_FILE} }}} auf allen verfügbaren Laufwerken nach dem `${GRUB_LOOPBACK_ISO_FILE}` sucht, und das Laufwerk, auf dem die Datei liegt, als '''/root''' setzt. Außerdem darf der Pfad auch keinen logischen Link beinhalten, weil GRUB 2 diesem nicht folgen kann. {{{#!vorlage Tabelle Einstellungen in der '''/etc/default/grub''' +++ `GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"` +++ `GRUB_CMDLINE_LINUX="locale=de_DE bootkbd=de console-setup/layoutcode=de"` }}} Mit diesen Einstellungen werden die Desktop- und die Tastatur-Einstellungen gleich auf Deutsch gestartet. Es können auch [:GRUB_2/Konfiguration#Variable-fuer-Kernelzeilen:weitere Parameter übergeben] werden. Auch der Eintrag für das ISO-Image kann alternativ entsprechend [:GRUB_2/Konfiguration#Eigene-Variablen: eigene Variablen] direkt eingebracht werden: {{{#!vorlage Tabelle Einstellungen in der '''/etc/default/grub''' +++ `export GRUB_LOOPBACK_ISO_FILE="/Pfad_zum_ISO/ubuntu-12.04-desktop-i386.iso"` }}} Dafür kann dann die relevante Zeile 2 im obigen [#Beispiel-Ubuntu-Iso Skript] entfallen. Wenn man das Live-System nicht nur benutzen, sondern auf der Festplatte installieren möchte, muss man vor der Installation das Image mittels {{{#!vorlage Befehl sudo umount -l -r -f /isodevice }}} aushängen, da sonst die Installation nicht möglich ist. Da das '''/isodevice''' ansonsten in Benutzung ist, kann es nicht automatisch von der Installtionsroutine ausgehängt werden. == Beispiel Lubuntu 18.04 64bit == {{{#!code bash #!/bin/sh -e export ISOFILE="/iso/lubuntu-18.04-desktop-amd64.iso" echo "Found ISOFILE image: ${ISOFILE}" >&2 cat << EOF menuentry "${ISOFILE}" { load_video insmod loopback insmod iso9660 insmod part_msdos insmod part_gpt insmod ext2 insmod ntfs insmod btrfs search -n -f --set=root ${ISOFILE} loopback loop ${ISOFILE} echo 'Loading Linux linux ...' linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=${ISOFILE} noprompt noeject echo 'Loading initial ramdisk ...' initrd (loop)/casper/initrd.lz } EOF exit 0 }}} Ein Menü Eintrag für Lubuntu. Das Iso liegt in diesem Beispiel im Ordner "/iso/...". Falls man ein BTRFS Dateisystem mit Subvolumes (z.B. @home) verwendet, lautet der Pfad zum Iso dann "/@home/iso/...". == Beispiel Arch Linux 2018.05.01 == {{{#!code bash #!/bin/sh -e export ISOFILE="/iso/archlinux-2018.05.01-x86_64.iso" export ISOPATH="/dev/disk/by-label/root" echo "Found ISOFILE image: ${ISOFILE}" >&2 cat << EOF menuentry "${ISOFILE}" { load_video insmod loopback insmod iso9660 insmod part_msdos insmod part_gpt insmod btrfs search -n -f --set=root ${ISOFILE} loopback loop ${ISOFILE} echo 'Loading Linux linux ...' linux (loop)/arch/boot/x86_64/vmlinuz img_dev=${ISOPATH} img_loop=${ISOFILE} earlymodules=loop echo 'Loading initial ramdisk ...' initrd (loop)/arch/boot/intel_ucode.img (loop)/arch/boot/x86_64/archiso.img } EOF exit 0 }}} Dieser Eintrag bootet das [https://www.archlinux.de Arch Linux] {de} Iso im Unterordner "iso" auf der Partition mit dem Label "root". In diesem Beispiel wird mit der initrd zusätzlich der Intel Mikrocode geladen (intel_ucode.img) == Kernel-Boot-Optionen für ISO ermitteln == Um ISO-Dateien erfolgreich booten zu können sind - wie man an den langen `GRUB_CMDLINE_LINUX` bzw. `linux`-Zeilen in den Beispielen sieht - die richtigen Kernel-Boot-Optionen von entscheidender Bedeutung. Diese sind jedoch von ISO zu ISO unterschiedlich. Die Optionen sind aber stets auf dem ISO erhalten, so dass man diese nur auslesen [2] muss, um die Optionen setzen zu können. In aller Regel befinden sich diese Optionen in der Datei '''isolinux.cfg''', die sich im Verzeichnis '''/isolinux''' innerhalb des ISO befindet. Dort kann man auch herauslesen, welche Dateien im ISO die zu ladende Kernel-Datei und Ramdisk enthalten. Bei den offiziellen Ubuntu-ISO-Dateien verzweigt die '''isolinux.cfg''' in weitere Dateien, so dass diese Informationen in der '''txt.cfg''' im Verzeichnis '''/isolinux''' zu finden sind. = Kaskadiertes Starten = Sofern man z.B. einen Headless-Server betreibt und diesen einschaltet, kann man ohne Monitor nicht erkennen, ob das Booten erfolgreich war oder nicht - schlimmer noch, man erkennt erst nach einem erfolglosen Verbindungsversuch z.B. über [:SSH:], dass etwas nicht stimmt. Nun kann man das System erneut starten und hoffen, dass es dann funktioniert - nur GRUB 2 startet (normalerweise) mit der gleichen Konfiguration. Und hier setzt jetzt das Kaskadierte Starten als Notfallbehandlung ("fallback-modus") an. Vorausgesetzt man hat ein Reserve-System in einer anderen Partition auf demselben Rechner oder externem Datenträger, dann kann man GRUB 2 so konfigurieren, dass nach einem erfolglosen Start automatisch das Reservesystem gestartet wird. War dieser Bootvorgang und die Reparatur erfolgreich, so wird beim nächsten Einschalten (oder Rebooten) wieder das (erste) Hauptsystem ausgewählt. == Fehler in GRUB abfangen == Um Fehler abzufangen, die von GRUB_2 erkannt werden können (z.B. dass nach einem Update die Kerneleinträge falsch sind), so bietet sich die nachfolgend beschriebene Prozedur an. === Vorbereitungen Grubfehler === {{{#!vorlage Tabelle Einstellungen in der '''/etc/default/grub''' +++ `GRUB_DEFAULT="0"` +++ `export GRUB_FALLBACK="2"` +++ `GRUB_TIMEOUT_STYLE=hidden` +++ `GRUB_TIMEOUT=10` +++ `GRUB_RECORDFAIL_TIMEOUT=10` }}} Die beiden Werte `GRUB_HIDDEN_TIMEOUT=` und `GRUB_HIDDEN_TIMEOUT_QUIET=` müssen auskommentiert bzw. gelöscht werden. Siehe auch die Ausführungen unter [:GRUB 2/Konfiguration#Die-Datei-etc-default-grub:] zur Datei '''/etc/default/grub'''. === Fallback-Skript === Man kopiert das nachfolgende Skript und benennt es '''01_fallback''', wobei es __nur__ darauf ankommt, dass dieses Skript unmittelbar nach dem Skript '''/etc/grub.d/00_header''' ausgeführt wird (siehe auch [:GRUB_2/Konfiguration#Die-Abarbeitungs-Reihenfolge-der-Skripte: Abarbeitungs-Reihenfolge]). {{{#!code bash #! /bin/sh -e if [ ! "x${GRUB_DEFAULT}" = "xsaved" ] ; then if [ "x${GRUB_FALLBACK}" = "x" ] ; then export GRUB_FALLBACK="" GRUB_FALLBACK=$( ls /boot | grep -c 'initrd.img' ) [ ${GRUB_DISABLE_LINUX_RECOVERY} ] || GRUB_FALLBACK=$(( ${GRUB_FALLBACK} * 2 )) fi echo "fallback modus set to menuentry=${GRUB_FALLBACK}" >&2 cat << EOF set fallback="${GRUB_FALLBACK}" EOF fi }}} Wurde die Vorgaben zu `GRUB_DEFAULT` einerseits und der adequate Eintrag im Skript zu `GRUB_FALLBACK` den eigenen Erfordernissen entsprechend in die '''/etc/default/grub''' eingetragen, so sind diese Werte statisch und müssen ggf. nach einem Kernelupdate manuell korrigiert werden. Wird z.B. nach den mit '''/etc/grub.d/10_linux''' erzeugten Kerneleinträgen ein Reserve-System durch ein geeignetes Skript eingetragen, so berücksichtig das obige Skript automatisch die Position dieses Menüeintrages auch über ein Kernelupdate hinaus mit folgenden {{{#!vorlage Tabelle Einstellungen in der '''/etc/default/grub''' +++ `GRUB_DEFAULT="0"` +++ `export GRUB_FALLBACK=""` }}} bzw. man verzichtet auf einen Eintrag der Variablen `GRUB_FALLBACK` an dieser Stelle. {{{#!vorlage Hinweis Dieser "Fallback-Modus" ist __nur__ wirksam, wenn GRUB 2 ohne manuellen Eingriff hochläuft. Wurde hingegen ein "fehlerhafter" Menü-Eintrag von Hand mittels der Pfeiltasten [[Vorlage(Tasten,up+down)]] und Betätigung von [[Vorlage(Tasten,Enter)]] aufgerufen, so erscheint die relevante Fehlermeldung. Dieses ist vom Konzept her so vorgesehen, um eine Fehlersuche aus dem GRUB-Menü heraus zu ermöglichen. }}} == Fehler im Betriebssystem abfangen == Fehler im Betriebssystem erkennt GRUB 2 mit der oben beschriebenen [#Fehler-in-Grub-abfangen Methode] nicht, nachdem das Laden der Kerneldateien erfolgreich war. Will man auftretende Fehler nach diesem Zeitpunkt abfangen, so muss man einen Neustart auf ein Reservesystem umleiten, welches in einer anderen Partition auf demselben Rechner oder einem externem Datenträger liegt. Angenommen das Haupt-System liegt z.B.: auf der ersten Menüposition ("0"), das Reserve-System dagegen auf der zweiten Menüposition ("1"). === Vorbereitung OS-Fehler === {{{#!vorlage Tabelle Einstellungen in der '''/etc/default/grub''' +++ `GRUB_DEFAULT="saved"` +++ `GRUB_TIMEOUT_STYLE=hidden` +++ `GRUB_RECORDFAIL_TIMEOUT=10` +++ `GRUB_TIMEOUT=10` }}} Die beiden Werte `GRUB_HIDDEN_TIMEOUT=` und `GRUB_HIDDEN_TIMEOUT_QUIET=` müssen auskommentiert bzw. gelöscht werden. === Umleitungs-Skript === {{{#!code bash #! /bin/sh -e echo "Menü zum Umleiten und Rückstellen eingefügt" >&2 cat << EOF menuentry "Hauptsystem Headless Server (0)" { set saved_entry="1" save_env saved_entry insmod ext2 insmod raid set root='(hd0,2)' search --no-floppy --label --set=root ROOT_MAIN linux /vmlinuz root=UUID=ae875d31-cc84-4349-95d7-01a82ad76d61 ro initrd /initrd.img } menuentry "Reservesystem Headless Server (1)" { set saved_entry="0" save_env saved_entry insmod ext2 insmod raid set root='(hd0,3)' search --no-floppy --label --set=root ROOT_SAVE linux /vmlinuz root=UUID=43c4345B-0c0a-4df6-8abe-8114b06393b2 ro initrd /initrd.img } EOF }}} === Rückstellungs-Skript === Nun würde nach einem (fehlerfreien) Booten und anschließendem Reboot bzw. Aus-/Einschalten anstelle des Haupt-Systemes das Reserve-System starten. Dieses muss noch wieder zurück gestellt werden. Das kann man wie im folgenden Beispiel über das Skript '''/etc/rc.local''' realisieren, jedoch sollte man auch die bessere Lösung über ein Skript im Verzeichnis '''/etc/init.d''' in Betracht ziehen, weil dann das Timing über die Dienste (runlevel) gezielter vorzunehmen ist. Noch besser allerdings ab Lucid Lynx (10.04 LTS) ist eine Integration in '''/etc/init''', weil dann die Voraussetzungen für ein Rückstellen an konkrete Bedingungen und nicht nur an eine zeitliche Anbindung möglich ist. In der '''/etc/rc.local''' trägt man vor exit 0 nun ein: {{{#!code bash grub-set-default 0 > /dev/null; }}} {{{#!vorlage Hinweis Im Prinzip ist auch eine Kombination aus beiden oben beschriebenen Methoden möglich. Nach einer Anpassung der Skripte an die eigenen Gegebenheiten und Erfordernisse sollte durch eine ausführliche Testphase der fehlerfreie Ablauf sicher gestellt werden. }}} = Ausführbarkeit der Skripte = Ein Skript kann von der '''update-grub'''- bzw. '''grub-mkconfig'''-Prozedur nur berücksichtigt werden, wenn es ausführbar ist. Dies erledigt man mit dem folgenden Kommando im Terminal: {{{#!vorlage Befehl sudo chmod +x /etc/grub.d/XX_EIGENES_SKRIPT }}} Hingegen kann man im Terminal mit: {{{#!vorlage Befehl sudo chmod -x /etc/grub.d/XX_EIGENES_SKRIPT }}} ein Skript von der Erfassung wieder ausschließen. `XX_EIGENES_SKRIPT` muss dabei mit dem Namen des eigens erstellten Skripts ersetzt werden. = Links = * [https://www.gnu.org/software/grub/manual/grub/ Grub Manual] {en} - bei Free Software Foundation in vielen Formaten (HTML, PDF, …) * [:GRUB_2: GRUB 2 Übersicht] {Übersicht} * [:GRUB_2/Grundlagen: GRUB 2 Grundlagen] * [:GRUB_2/Installation: GRUB 2 Installation] * [:GRUB_2/Konfiguration: GRUB 2 Konfiguration] * [:GRUB_2/Aussehen: GRUB 2 optisch anpassen] * [:GRUB_2/Problembehebung: GRUB 2 Probleme und Lösungen] * [:GRUB_2/Reparatur: GRUB 2 Reparatur] * [:GRUB_2/Shell: GRUB 2 Shell] ## * [:Archiv/GRUB_2/Terminalbefehle: GRUB 2 Terminalbefehle] * [:GRUB_Umgebung_analysieren: GRUB 2 Umgebung analysieren] * [:EFI_Bootmanagement:] {Übersicht} Details zur EFI-Installation und Einsatz von GRUB 2 #tag: System, Bootloader, iso aus grub