ฉันกำลังทำงานกับเฟรมเวิร์กการอัปเดตซอฟต์แวร์ อัพเดท. สำหรับแผนการปรับปรุง ฉันเลือกวิธีการทำสำเนาคู่ ฉันได้ติดตั้ง Ubuntu 20.04 บนอุปกรณ์เป้าหมาย (เดสก์ท็อปพีซี -->i5,32GB SSD,BIOS,..) เพื่อทดสอบและแบ่งพาร์ติชันตามนั้น
/dev/sda1 --/บูต
/dev/sda2--/
/dev/sda3--/root2
/dev/sda4 --/ข้อมูล
เพื่อจุดประสงค์ในการทดสอบ ฉันสร้างอิมเมจระบบไฟล์รูทจากระบบโฮสต์ (/dev/sda2) โดยใช้คำสั่ง "dd" ฉันกำหนด UUID และป้ายกำกับใหม่ให้กับรูปภาพโดยใช้คำสั่ง "tune2fs" และ "e2label"
dd if=/dev/sda2 of=rootfs.img สถานะ=ความคืบหน้า
e2label rootfs.img รูท 2
e2fsck -fy rootfs.img
tune2fs -U rootfs.img แบบสุ่ม
จำเป็นต้องมีกลไกสำหรับการประสานงานระหว่าง boot loader และ update agent เพื่อที่จะบูตระบบด้วยพาร์ติชั่น rootfs รองหลังจากอัพเดตสำเร็จbootloader ควรตรวจสอบให้แน่ใจว่าได้โหลดพาร์ติชัน rootfs ใด (A หรือ B) แล้ว
Ubuntu ใช้ GRUB เป็นตัวโหลดบูตมาตรฐาน GRUB จัดเตรียม "บล็อกสภาพแวดล้อม" ซึ่งสามารถใช้เพื่อบันทึกสถานะจำนวนเล็กน้อย (/boot/grub/grubenv) เอเจนต์การอัปเดต "SWUpdate" มีตัวจัดการ bootloader เพื่อจัดการไฟล์นี้ SWupdate สามารถเพิ่มตัวแปรสภาพแวดล้อมให้กับไฟล์นี้ได้ SWupdate สามารถเรียกใช้สคริปต์ก่อนและหลังการติดตั้งอิมเมจ (ก่อน-หลังการติดตั้ง)
ฉันได้เขียนสคริปต์ทุบตีที่อ่านพาร์ติชัน rootfs ปัจจุบันจากบรรทัดคำสั่งเคอร์เนล (/proc/cmdline) และตัวแปรสภาพแวดล้อมจากบล็อกสภาพแวดล้อม GRUB (/boot/grub/grubenv) เพื่ออัปเดตพาร์ติชัน rootfs หลังการอัปเดต ดำเนินการผ่านไฟล์คอนฟิกูเรชัน bootloader เริ่มต้น (/etc/default/grub) ที่ระบบถูกบูท
CONFIG_FILE=/etc/default/grub
ROOTFS1_UUID=$(blkid -o ค่า -s UUID /dev/sda2)
ROOTFS2_UUID=$(blkid -o ค่า -s UUID /dev/sda3)
ฟังก์ชัน get_UUID_of_current_boot_device () {
สำหรับฉันใน `cat /proc/cmdline`; ทำ
กรณี "$i" ใน
ราก=*)
ROOT="${i#root=UUID=}"
;;
เอสแซค
เสร็จแล้ว
}
ฟังก์ชัน get_partition_number_of_current_boot_device () {
ถ้า [[ $ROOT = $ROOTFS1_UUID ]]; แล้ว
CURRENT_PARTITION="2";
elif [[ $ROOT = $ROOTFS2_UUID ]]; แล้ว
CURRENT_PARTITION="3";
อื่น
echo "เกิดข้อผิดพลาดโดย Partitionshema!!"
ไฟ
}
ฟังก์ชัน get_bootloader_env () {
สำหรับฉันใน `cat /boot/grub/grubenv`; ทำ
กรณี "$i" ใน
บูตพาร์ท=*)
BOOT_DEVICE="${i#bootpart=}"
;;
เอสแซค
เสร็จแล้ว
}
ฟังก์ชัน set_boot_device_UUID() {
ถ้า [ $BOOT_DEVICE = "2" ]; แล้ว
BOOT_DEVICE_UUID="$ROOTFS1_UUID";
เอลลิฟ [ $BOOT_DEVICE = "3" ]; แล้ว
BOOT_DEVICE_UUID="$ROOTFS2_UUID";
อื่น
เสียงสะท้อน "";
BOOT_DEVICE_UUID="$ROOT";
ไฟ
}
เท่าที่ฉันได้อ่านมา เพื่อแก้ไขพารามิเตอร์บรรทัดคำสั่งเคอร์เนลอย่างถาวร พารามิเตอร์ที่จำเป็นจะต้องกำหนดค่าในบรรทัด GRUB_CMDLINE_LINUX_DEFAULT หรือในบรรทัด GRUB_CMDLINE_LINUX ในสคริปต์ของฉัน ฉันแก้ไขบรรทัดนี้เพื่อให้ตัวแปร $BOOT_DEVICE_UUID ควรเป็นพาร์ติชัน rootfs ที่ควรบูตหลังจากรีบูตเสมอ
sed -i "s/\(GRUB_CMDLINE_LINUX *= *\).*/\1\"$BOOT_DEVICE_UUID\"/" $CONFIG_FILE;
น่าเสียดายที่ไม่ได้ผล ฉันคิดว่าค่าของตัวแปร "รูท" ที่มีอยู่ในบรรทัดคำสั่งจะถูกแทนที่ด้วยค่าที่ฉันส่งผ่าน
ตัวโหลดการบูตควรเลือกผ่านตัวแปรสภาพแวดล้อมซึ่งควรโหลดพาร์ติชัน Rootfs ซึ่งมีระบบ Linux ใครช่วยอธิบายให้ฉันฟังว่าข้อผิดพลาดของฉันอยู่ที่ไหน และมีใครช่วยยกตัวอย่างที่เป็นรูปธรรมเกี่ยวกับหัวข้อนี้ให้ฉันได้ไหม