Creiamo un Initramfs personalizzato su Linux

Vediamo come creare un Initramfs completamente personalizzato su Linux.

Buongiorno a tutti; a volte capita, per scelta o per necessità, di dover creare un cosiddetto Initramfs, cioè un'immagine di disco caricata contestualmente al kernel che dice al sistema come completare una certa procedura di avvio, per esempio montare un filesystem con LVM prima di montarlo e procedere all'avvio del pc dallo stesso volume LVM.

Esistono molti metodi per creare un initramfs, per gentoo ci sono gli script GenKernel oppure Dracut o ancora, si può usare better-initramfs.

Io ho voluto andare più a fondo e creare da zero il mio personalissimo Initramfs, cosa che molte volte richiede la generazione di un codice eseguibile in C per l'init. Ma se l'immagine viene ben costruita è possibile scrivere l'init in semplice codice Bash. Vediamo come.

I prerequisiti sono gli stessi di qualunque altro sistema su cui deve girare un initramfs, iniziamo creando la struttura di cartelle su cui andremo a lavorare:

mkdir /usr/src/initramfs
cd /usr/src/initramfs
mkdir -p bin dev etc lib lib64 mnt/root proc root sbin sys

Ora è necessario avere a disposizione un ambiente dove il nostro init possa venire eseguito. Invece di ricompilare una miriade di programmi per poi copiarli nella nostra immagine, senza mai vedere la fine è possibile usare busybox; che contiene un ambiente shell completo.

Verifichiamo che busybox sia compilato con librerie statiche:

ldd /bin/busybox

Se ldd risponde "Not a dynamic executable" possiamo copiarlo direttamente nella nostra cartella.

cp -a /bin/busybox /usr/src/initramfs/bin/busybox

Se al posto dell'avviso di cui sopra vi esce un elenco di librerie è necessario ricompilare busybox, per esempio usando la USE flag "static" per gentoo.

Ora copia alcuni nodi importanti:

cp -a /dev/{console,null,sda1,tty} /usr/src/initramfs/dev/

Ora aggiungete tutti i programmi che possono essere utili all'avvio del vostro pc, tenendo conto che più ne aggiungete più il vostro initramfs sarà pesante, inoltre busybox contiene moltissime funzioni, anche un editor in stile VI.

Nel mio caso la struttura delle cartelle è:

PenazMW initramfs #  tree

.

|-- bin

|   `-- busybox

|-- dev

|   |-- console

|   |-- null

|   |-- sda1

|   `-- tty

|-- etc

|-- init

|-- lib

|-- lib64

|-- mnt

|   `-- root

|-- proc

|-- root

|-- sbin

|   |-- lvm

|   `-- mdev -> /usr/src/initramfs/bin/busybox

Avendo la root su un volume LVM ho dovuto ricompilare LVM2 con la USE flag "Static" ed ho deciso di popolare /dev tramite mdev, praticamente udev per busybox.

Ora arriva la parte creativa, la scrittura dello script di init, qui molto dipende dalle vostre esigenze, nel mio caso avremo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/busybox sh
#Shell di emergenza in caso di problemi
rescue_shell() {
echo "Something went wrong. Dropping you to a shell."
busybox --install -s
exec /bin/sh
}
#montaggio proc e sys e tmpfs
mount -t proc none /proc
mount -t sysfs none /sys
#Avvio Mdev
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
#Avvio Lvm2
lvm lvchange -aly vg
lvm vgscan --mknodes
# montaggio Root
mount -o ro -t ext4 /dev/mapper/vg-Root /mnt/root || rescue_shell
# Pulizia
umount /proc
umount /sys
# Chroot e passaggio al vero init
echo "Switching to real root..."
exec switch_root /mnt/root /sbin/init

Particolare nota merita la funzione rescue_shell che, nel caso non fosse possibile montare la root, invece di provocare un kernel panic fa in modo che il sistema ricada con leggiadria in una console di emergenza da dove è possibile analizzare il problema.

I superutenti più arditi possono far leggere allo script la linea di comando ed inventare un nuovo argomento (tipo "shell") per accedere direttamente alla shell di emergenza, senza avviare completamente il sistema.

Ora è il momento di generare l'immagine con cui andremo ad avviare il sistema. Sono pochi comandi.

cd /usr/src/initramfs
find . -print0 | cpio --null -ov --format=newc|gzip -9 > <percorso di salvataggio>/initramfs.gz

È importante non salvare il file all'interno della /usr/src/initramfs altrimenti succederanno degli spiacevoli inconvenienti.

Ora è sufficiente copiare il file initramfs.gz dalla cartella di salvataggio alla /boot di sistema e configurare opportunamente il vostro boot manager, sia esso Grub 0.97, Grub2, LiLo o Burg.

Se tutto è andato come doveva al successivo avvio dovreste avere un initramfs funzionante.

Buon smanettamento a tutti!

Penaz.

social