Grub Chainload

Vorbemerkung

Diese Anleitung ist für Computer geschrieben, die auf PC-BIOS mit MBR-Partitionstabelle basieren, nicht für UEFI.
Im Text benutzen wir den Begriff "Grub", der die Version 2, also "Grub 2" wiedergeben soll.
Bemerkung:
Ich selbst habe kein UEFI, aber, ich habe gehört, dass das, um was es hier geht, mit UEFI überflüssig sein soll, weil das Starten mehrerer Systeme damit angeblich kein Problem sei.
 

Mehrere Systeme mit einer Grub-Installation oder auch mit mehreren Grub Installationen?

Viele Benutzern hegen früher oder später den Wunsch, auf ihrem Rechner mehrere Betriebssysteme (z. B.: BSD,Linux oder Windows) installiert haben zu wollen.
 
Wie verhält sich hier ein Bootloader wie Grub, wenn es darum geht, verschiedene Betriebssystem-Installationen zu starten?

Wendet man die herkömmliche Methode an, die Grub dafür vorgesehen hat, kann das schnell sehr unübersichtlich werden:
Grub bringt ein Skript namens "os-prober" (Pfad: /etc/grub.d/30_os-prober) mit, das bei der Installation von Grub und auch bei jedem Aufruf von

sudo update-grub
nach allen Betriebssystemen auf dem System (egal auf welchen Festplatten oder sonstigen angeschlossenen Speichermedien!) sucht und diese dann automatisch in das Grub-Menü aufnimmt.
Genauer gesagt: Es wird ein Grub-Menü-Eintrag für jeden installierten Kernel jeden Systemes erzeugt. Das ist einerseits sehr bequem, weil es eben ein Automatismus ist, andererseits ist es auf Dauer nicht sehr komfortabel, weil, wenn es in einem Nebensystem ein Kernelupdate gegeben hat, immer danach das Hauptsystem gebootet und dort wieder
sudo update-grub
gestartet werden muss, um den neuen Kernel des Nebensystems von Grub "entdecken“ und im Grub-Menü anzeigen zu lassen.
Zudem wird das Grub-Menü durch die zusätzlichen Einträge aufgebläht und unübersichtlich. Das gilt natürlich umso mehr, je mehr Systeme auf der Maschine installiert sind.
Trotz dieser Nachteile mag diese herkömmliche Methode, bei zwei auf der Maschine installierten Linux-Systeme, noch praktikabel sein, sind es aber mehr als zwei Systeme, ist dieses Vorgehen nicht mehr zu empfehlen.
 

Alternative: Chain-Loader einsetzen

Hier bietet Grub die Funktion "chainloader" an.

Mit dieser Funktion hat jedes installierte System einen eigenen Bootloader mit Grub, der nur die Einträge für dieses System enthält.
Bei einem Kernelupdate der einzelnen System wird der neue Eintrag für den neuen Kernel automatisch, ohne weiteres manuelles Eingreifen und nur in den Grub des jeweiligen Systems, aufgenommen.

Bemerkung:
Wenn Du ein Windows-Dualboot eingerichtet hast, ist das im Prinzip schon ein Chainloading:
Denn, das ist nichts anderes, als dass der Grub im MBR – also der, der zuerst startet, wenn Du Dein System hoch fährst, einen anderen Bootloader "in Kette", daher der Name (engl. chain= die Kette), aufruft, eben genau den Windows-Bootloader.

Dieses Ketten-System setzt man nun mit einem zweiten Grub für ein nebenher installiertes zweites Linux-System ein oder für ein drittes, viertes etc.
 

Zwei wichtige Begriffserklärungen

Bevor wir in die Tiefe gehen, kurz zwei, für den weiteren Verlauf, wichtige Begriffserklärungen:

"Hauptsystem" = Das installierte Linux, das Grub in den MBR der ersten Festplatte geschrieben (installiert) hat, aus dem der Computer überhaupt gestartet wird.
"Nebensystem" = Das installierte Linux, das Grub nicht in den MBR der ersten Festplatte geschrieben hat, sondern z. B. in den PBR, der Startpartition der Installation.

Klingt alles ziemlich akademisch und hölzern, ich weiß. Aber, hier muss ich einen meiner ehemaligen Mathe-Lehrer zitieren, der zu sagen pflegte: "Leude, das muss verstanden sein!“ Wenn nicht, dann nochmal lesen, denn das ist wichtig.
 

Was man bei der Installation beachten muss

Folgendes Szenario:

sudo fdisk -l
zeigt bei mir z.B.
  Gerät  boot.     Anfang        Ende     Blöcke   Id  System
/dev/sda1   *        2048      206847      102400    7  HPFS/NTFS/exFAT
/dev/sda2          206848    41166847    20480000   83  Linux
/dev/sda3        41166848    57550847     8192000   82  Linux Swap / Solaris
/dev/sda4        57552894   224673791    83560449    5  Erweiterte
/dev/sda5        57552896    88272895    15360000   83  Linux
(…)

Die Ausgabe des obigen Befehls und damit die Festplatte hat noch mehrere Zeilen, die hier, wie auch die angezeigte NFTS-Partition (Windows), ignoriert werden können.
Diese erste Platte "/dev/sda", ist auch die Start-Festplatte und als solche im BIOS eingestellt.

Hier sind zwei Linux-Systeme installiert: Auf "/dev/sda2" und auf "/dev/sda5".

Wem diese Bezeichnungen wie "/dev/sda2" noch fremd sind, sollte das hier zuerst lesen:
http://wiki.ubuntuusers.de/Datenträger

Das Hauptsystem wurde dann auf "/dev/sda2" installiert und diese Installation hat Grub in den MBR von "/dev/sda", der Festplatte und nicht der Partition, geschrieben und deshalb steht hier keine Zahl dahinter wie bei "/dev/sda2" z.B.

Als Nebensystem wurde Ubuntu auf "/dev/sda5" installieren, weil wir eben doch einmal dieses sagenhafte Unity unbedingt haben wollen, Mint soll unser Hauptsystem bleiben.

Bei der Installation des Nebensystems muss Folgendes gemacht werden: Wir wählen zwingend bei der Installation bei dem Abschnitt "Festplattenspeicher zuweisen" die Möglichkeit "Etwas anderes", also die manuelle Partitionierung bzw. Zuweisung (tun wir nebenbei sowieso, weil wir ja schon bestehende Partitionen haben, und nur hier dem System, also dem Einhängepunkt "/", eine Partition zuweisen wollen. Das geht nur mit "Etwas anderes")

Im Installer-Fenster "Festplattenspeicher zuweisen" hat man unten eine Zeile für die Auswahl des Installationsortes von Grub. Bei Unklarheiten bitte vor der Installation anhand der Bilder hier:
Auswahl der Partition, Partitionierung und Bootloader
nochmal vor Augen führen, damit man diesen Punkt ja nicht verpasst!

Hier wird der Installationsort für Grub geändert, wir installieren ja ein Nebensystem: Wir müssen hier also als "Device for boot loader installation" = "/dev/sda5" angeben.
So, jetzt kann man der Installation ihren gewohnten Lauf lassen.
 

Was ist nach der Installation des Nebensystems zu beachten?

Wenn wir nach Abschluss der Installation das System neu starten, wird sich uns zunächst überhaupt keine sichtbare Veränderung zeigen. Grub ist ja noch der alte von Mint, und das neue System ist dort auch noch nicht zu sehen.

Würden wir jetzt nicht den Chainload anpeilen, sondern die "herkömmliche", also besagte os-prober-Methode wählen, dann müssten wir nichts anderes machen, als Mint zu booten, dort

sudo update-grub
laufen zu lassen und nach einem Reboot würden wird dann das neu installierte Ubuntu in Form von zusätzlichen Grub-Menü-Einträgen im Hauptsystem-Grub entdecken.

Aber genau das wollen wir ja nun nicht mehr! Sondern, wir wollen jetzt eben den Chainload einsetzen.
Die Voraussetzungen dafür sind gegeben:
Wir haben (Windows lassen wir jetzt mal weg) zwei Linux Installationen, also zwei Glieder für unsere Kette (chain).
Und wir haben zwei Grub Installationen, die erste von Mint im MBR von "/dev/sda" und die zweite, von Ubuntu im PBR von "/dev/sda5".

1. Schritt
Die Konfiguration des Hauptsystems-Grub verändern.
Linux Mint, das Hauptsystem starten.
Dort fügen wir jetzt in das Grub-Menü einen neuen Eintrag, unseren Chainload-Eintrag, selbst hinzu. Das geht einfach, indem man einen solchen Eintrag in die schon bestehende Datei /etc/grub.d/40_custom hineinschreibt. Diese Datei hat den einen Zweck: Sie beinhaltet eigene, vom Benutzer hinzugefügte, Grub-Menü-Einträge.

Man öffnet per Editor diese Datei mit Rootrechten:
Cinnamon:

gksudo gedit /etc/grub.d/40_custom

MATE:

gksudo pluma /etc/grub.d/40_custom

XFCE:

gksudo leafpad /etc/grub.d/40_custom

KDE:
Alt + F2 drücken, dann in die Eingabezeile oben am Bildschirmrand eingeben:

kdesudo kate /etc/grub.d/40_custom

Die Datei öffnet sich und erscheint zunächst nur mit dem Inhalt:

#!/bin/sh
exec tail -n +3 $0
 # This file provides an easy way to add custom menu entries.  Simply type the
 # menu entries you want to add after this comment.  Be careful not to change
 # the 'exec tail' line above.

Diesen Inhalt lässt man so stehen, und fügt jetzt zusätzlich hinzu:

menuentry "Ubuntu  on /dev/sda5" {
insmod ext2
   set root=(hd0,5)
   chainloader +1
}

und speichert das Ganze dann ab.

Die Datei sieht also dann so aus:

#!/bin/sh
exec tail -n +3 $0
 # This file provides an easy way to add custom menu entries.  Simply type the
 # menu entries you want to add after this comment.  Be careful not to change
 # the 'exec tail' line above.
menuentry "Ubuntu  on /dev/sda5" {
insmod ext2
   set root=(hd0,5)
   chainloader +1
}

Dazu noch zwei Bemerkungen: Der Name, der dann nachher im Grub-Menü erscheint, kann völlig frei gewählt werden. Hier könnte also stattdessen als erste Zeile auch stehen:

menuentry "Mein tolles Unity-Ubuntu" {

Die Zählung in der Zeile

set root=(hd0,5)

verhält sich so, dass die Festplatten (Ziffer VOR dem Komma) von 0 weg gezählt werden (hier also 0 für sda, die erste Platte), die Partitionen (Ziffer NACH dem Komma) aber von 1 weg (das war bei Grub legacy anders, daher das hier beachten, es steht also bei uns hier richtig hd0,5 für sda5).

Die Datei muss gespeichert werden und den Befehl im Terminal

sudo update-grub
aufrufen.

Das System einmal neu starten: Grub muss jetzt diesen neuen Eintrag zusätzlich zeigen, diesen Eintrag wählen und jetzt wird der zweite Grub von Ubuntu aufgerufen.
 

Kleine Nacharbeiten

2. Schritt
Hat man Windows installiert bitte vorher letzten Abschnitt beachten!
Funktioniert dies, dann muss man nur noch, um in den Genuss der besagten Entschlackung des Grub-Menüs zu kommen, os-prober ausgeschaltet werden, das wir den ja jetzt nicht mehr brauchen, weil wir die Grub-Angelegenheiten unseres Zweit-OS selbst in die Hand genommen haben. Das geht einfach mit

sudo chmod -x /etc/grub.d/30_os-prober
sudo update-grub

Übrigens brauchen wir dieses os-prober ja auch nicht im Grub unseres Nebensystems, und es ist schöner, es auch dort auszuschalten.
Hierzu Ubuntu starten und die beiden letzten Befehle wiederholen.

Das war es eigentlich schon. Für alle weiteren Systeme ist das ganz gleich immer wieder zu machen. Also bei jeder Installation eines weiteren Systems beachten:
Grub bei der Installation in die Root-Partition installieren (Einhängepunkt /).
Danach im Hauptsystem in /etc/grub.d/40_custom den neuen Eintrag dafür mit der richtigen Nummerierung hinzufügen. Im jeweils neuen System dann noch os-prober ausschalten.
Das war schon alles.

Es kann passieren das nach dem ausschalten von os-prober der Grub beim Systemstart nicht mehr angezeigt wird. Ist das der Fall muss im Hauptsystem die Datei /etc/default/grub bearbeitet werden. Dazu wird die Datei im Editor geöffnet, z.B. mit

gksudo gedit /etc/default/grub
(Der Befehl gilt für Cinnamon, bei Mate, KDE oder xfce muss der Editor angepasst werden (so wie beim Editieren der "/etc/grub.d/40_custom" weiter oben))

In dieser Datei wird dann die Zeile

GRUB_HIDDEN_TIMEOUT=0
auskommentiert, also vorne ein '#' eingefügt, das sieht dann so aus:
#GRUB_HIDDEN_TIMEOUT=0
Danach die Datei speichern und den Editor schließen. Jetzt nochmal
sudo update-grub
ausführen, dann wird der Grub beim Systemstart wieder angezeigt.

Windows in die /etc/grub.d/40_custom verlegen

Wenn auch Windows auf dem Rechner installiert ist, muss man, weil man ja os-prober, das normalerweise dafür sorgt, dass Windows "entdeckt" wird, abschaltet, den Windows-Eintrag selbst als zusätzlichen Eintrag in die /etc/grub.d/40_custom kopieren.
Dazu geht man wie folgt vor: BEVOR man os-prober aussschaltet, sucht man sich seinen Windows-Eintrag in der Datei /boot/grub/grub.cfg (das ist die Datei, die durch den Befehl sudo update-grub immer neu erzeugt wird, und die im Endeffekt bestimmt, was Grub macht, enthält und wie er aussieht).
Man öffnet also die Datei (Root-Rechte nicht nötig, da nur herauskopiert werden muss), etwa im Terminal mit

cat /boot/grub/grub.cfg
und sucht den Eintrag und kopiert ihn heraus. Bei mir ist das etwa

menuentry "Windows 7 (loader) (on /dev/sda1)" --class windows --class os {
        insmod part_msdos
        insmod ntfs
        set root='(hd0,msdos1)'
        search --no-floppy --fs-uuid --set=root 2CBE2021BE1FE1DE
        chainloader +1
}

Den kopiert man dann anschließend einfach auch zusätzlich in die /etc/grub.d/40_custom hinein, speichert wieder und macht wie immer

sudo update-grub

Jetzt kann man ohne Sorge os-prober mit

sudo chmod -x /etc/grub.d/30_os-prober
sudo update-grub

ausschalten und Windows wird weiterhin da sein.

Kleiner Tipp am Rande: Sollte man os-prober zu früh schon ausgeschaltet haben, und dann also keinen Windows-Eintrag mehr in der /boot/grub/grub.cfg haben, kann man ihn natürlich vorübergehend wieder aktivieren mit

sudo chmod +x /etc/grub.d/30_os-prober
Dann wieder
sudo update-grub

Dann aus der grub.cfg herauskopieren in die 40_custom wie oben beschrieben, und erst danach wieder ausschalten mit

sudo chmod -x /etc/grub.d/30_os-prober
und
sudo update-grub