În prezent lucrez la cadrul de actualizare software swupdate. Ca schemă de actualizare, am ales abordarea cu copie dublă. Am instalat Ubuntu 20.04 pe dispozitivul meu țintă (desktop pc -->i5,32GB SSD,BIOS,..) pentru a-l testa și a partiționat în consecință.
/dev/sda1 --/boot
/dev/sda2 --/
/dev/sda3 --/root2
/dev/sda4 --/data
În scopuri de testare, am creat o imagine a sistemului de fișiere rădăcină din sistemul gazdă (/dev/sda2) folosind comanda „dd”. Am atribuit un nou UUID și o etichetă imaginii folosind comenzile „tune2fs” și „e2label”.
dd if=/dev/sda2 of=rootfs.img status=progress
e2label rootfs.img root2
e2fsck -fy rootfs.img
tune2fs -U aleator rootfs.img
Este necesar să existe un mecanism de coordonare între încărcătorul de pornire și agentul de actualizare pentru a porni sistemul cu partiția secundară rootfs după o actualizare cu succes.Bootloader-ul ar trebui să se asigure care partiție rootfs (A sau B) este încărcată.
Ubuntu folosește GRUB ca încărcător de pornire standard. GRUB oferă un „bloc de mediu” care poate fi folosit pentru a salva o cantitate mică de stare (/boot/grub/grubenv). Agentul de actualizare „SWUpdate” are un handler de bootloader pentru a gestiona acest fișier. SWupdate poate adăuga variabile de mediu la acest fișier. SWupdate poate apela scripturi înainte și după instalarea imaginilor (pre-postinstalare).
Am scris un script bash care citește partiția rootfs curentă din linia de comandă a kernelului (/proc/cmdline) și variabilele de mediu din blocul de mediu GRUB (/boot/grub/grubenv) pentru a actualiza partiția rootfs după actualizare procesează prin fișierul de configurare implicit al bootloaderului (/etc/default/grub) cu care este pornit sistemul.
CONFIG_FILE=/etc/default/grub
ROOTFS1_UUID=$(blkid -o valoare -s UUID /dev/sda2)
ROOTFS2_UUID=$(blkid -o valoare -s UUID /dev/sda3)
funcția get_UUID_of_current_boot_device() {
pentru i în `cat /proc/cmdline`; do
cazul „$i” în
root=*)
ROOT="${i#root=UUID=}"
;;
esac
Terminat
}
funcția get_partition_number_of_current_boot_device() {
dacă [[ $ROOT = $ROOTFS1_UUID ]]; atunci
CURRENT_PARTITION="2";
elif [[ $ROOT = $ROOTFS2_UUID ]]; atunci
CURRENT_PARTITION="3";
altfel
echo „Eroare de Partitionshema!!”
fi
}
funcția get_bootloader_env() {
pentru i în `cat /boot/grub/grubenv`; do
cazul „$i” în
bootpart=*)
BOOT_DEVICE="${i#bootpart="
;;
esac
Terminat
}
funcția set_boot_device_UUID() {
dacă [ $BOOT_DEVICE = "2" ]; atunci
BOOT_DEVICE_UUID="$ROOTFS1_UUID";
elif [ $BOOT_DEVICE = "3" ]; atunci
BOOT_DEVICE_UUID="$ROOTFS2_UUID";
altfel
ecou "";
BOOT_DEVICE_UUID="$ROOT";
fi
}
Din câte am citit până acum, pentru a modifica permanent parametrii liniei de comandă a kernelului, parametrii necesari trebuie configurați în linia GRUB_CMDLINE_LINUX_DEFAULT sau în linia GRUB_CMDLINE_LINUX. În scriptul meu am modificat această linie astfel încât variabila $BOOT_DEVICE_UUID să fie întotdeauna partiția rootfs care ar trebui să fie pornită după repornire.
sed -i "s/\(GRUB_CMDLINE_LINUX *= *\).*/\1\"$BOOT_DEVICE_UUID\"/" $CONFIG_FILE;
Din păcate, asta nu a funcționat, m-am gândit că valoarea variabilei existente „rădăcină” în linia de comandă va fi înlocuită cu valoarea pe care am transmis-o.
Încărcătorul de pornire ar trebui să selecteze cumva prin variabilele de mediu care partiție Rootfs, care conține sistemul Linux, ar trebui să fie încărcată. Ar putea cineva să-mi explice, vă rog, unde este greșeala mea și ar putea cineva să-mi dea un exemplu concret despre acest subiect?