将Arch Linux系统安装在可移动设备上的要点
前言
最近在折腾将arch linux安装在可移动硬盘上,将踩坑的点在此文章做记录。
安装系统
安装系统时最好使用虚拟机连接你的可移动设备进行安装,若用真机小心你的真机数据以及你的引导,很多发行版不能自定义grub-install参数,导致做不到随插随用。可以先看看修改引导部分就明白为啥了。
随后就可以按照网上的教程(以arch linux为例,推荐此教程)正常安装系统。
在安装好桌面环境,以及安装完常用软件后,先不要安装显卡驱动,参照以下内容即可。
为了让随插随用的linux系统(linux to go)有较好的兼容性,参照Arch Linux 维基安装以下开源驱动。
pacman -S xf86-video-vesa xf86-video-ati xf86-video-intel xf86-video-amdgpu xf86-video-nouveau xf86-video-fbdev
修改fstab
为了在排错时更好的识别设备,可以修改/etc/fstab
中的UUID
为LABEL
。
当然也可以不修改,只是为了更好的识别设备。
如果你和我一样是用的btrfs,并且也是按照的此教程安装的系统。那么label应该已经设置,通过以下命令修改分区标签。
swap 使用[util-linux]包
swaplabel -L "new label" /dev/XXX`
ext2/3/4 使用[e2fsprogs]包
e2label /dev/XXX "new label"
btrfs 使用[btrfs-progs]包
btrfs filesystem label /dev/XXX "new label"
fat/vfat 使用[dosfstools]包
fatlabel /dev/XXX "new label"
注意:
- 设置标签时swap分区或者主分区需要取消挂载,swap分区可以先使用以下命令再设置标签。而对于主分区(rootfs)只能使用livecd设置标签。
swapoff /dev/XXX
- EFI分区的标签最好设置为全大写字母,防止bios不兼容。
设置标签后即可修改/etc/fstab
中的UUID
为LABEL
,修改完后如下所示。
使用如下命令即可直接使用LABEL,无需手动修改。
genfstab -U / > /etc/fstab
# /dev/sda3 LABEL=myArch
LABEL=myArch / btrfs rw,relatime,compress=zstd:3,space_cache=v2,subvol=/@ 0 0
# /dev/sda3 LABEL=myArch
LABEL=myArch /home btrfs rw,relatime,compress=zstd:3,space_cache=v2,subvol=/@home 0 0
# /dev/sda1
LABEL=BOOT_MYARCH /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2
# /dev/sda2
LABEL=swap_myArch none swap defaults 0 0
修改initramfs配置文件
使用编辑器打开/etc/mkinitcpio.conf
,将block
和keyboard
hook 移动到autodetect
hook 之前。这样才能在分别需要早期用户空间中不同模块的系统上启动。如下所示
HOOKS=(base udev block keyboard autodetect microcode modconf kms keymap consolefont filesystems fsck)
如果你和我一样使用btrfs,也需要将btrfs
添加到MODULES
里面,否则可移动设备在别的电脑启动可能会出现无法挂载rootfs的错误。如下所示
MODULES=(btrfs)
最后执行以下命令生成initramfs。
mkinitcpio -P
修改引导
在系统引导时也可以用标签代替UUID,为了确保某些奇怪情况下uuid在不同电脑上不同导致无法引导进入系统。
由于grub默认不支持使用LABEL
,因此需要修改生成grub的脚本。
以下内容参考自此网页
使用你喜欢的编辑器打开/etc/grub.d/10_linux
,在第52-66行附近,如下所示
# btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
# and mounting btrfs requires user space scanning, so force UUID in this case.
if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
|| ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
&& [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
|| ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
&& ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
|| ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
LINUX_ROOT_DEVICE=${GRUB_DEVICE}
elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
|| [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
else
LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
fi
这一行 LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
之下添加内容,如下所示
# btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
# and mounting btrfs requires user space scanning, so force UUID in this case.
if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
|| ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
&& [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
|| ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
&& ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
|| ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
LINUX_ROOT_DEVICE=${GRUB_DEVICE}
elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
|| [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
else
LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
GRUB_DEVICE_LABEL="$(blkid -l -t UUID=${GRUB_DEVICE_UUID} -s LABEL -o value)"
. /etc/default/grub
if [ "x${GRUB_ENABLE_LINUX_LABEL}" = "xtrue" ] \
&& test -e "/dev/disk/by-label/${GRUB_DEVICE_LABEL}" ; then
LINUX_ROOT_DEVICE=LABEL=${GRUB_DEVICE_LABEL}
fi
fi
如果是xen,对于/etc/grub.d/20_linux_xen
也做同样修改,当然对于我们这种情况没必要。
打开/usr/share/grub/grub-mkconfig_lib
,在153行-171行左右,如下所示
# If there's a filesystem UUID that GRUB is capable of identifying, use it;
# otherwise set root as per value in device.map.
fs_hint="`"${grub_probe}" --device $@ --target=compatibility_hint`"
if [ "x$fs_hint" != x ]; then
echo "set root='$fs_hint'"
fi
if [ "x${GRUB_DISABLE_UUID}" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then
hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints=
if [ "x$hints" != x ]; then
echo "if [ x\$feature_platform_search_hint = xy ]; then"
echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
echo "else"
echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}"
echo "fi"
else
echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}"
fi
fi
IFS="$old_ifs"
}
修改为
# If there's a filesystem UUID that GRUB is capable of identifying, use it;
# otherwise set root as per value in device.map.
fs_hint="`"${grub_probe}" --device $@ --target=compatibility_hint`"
if [ "x$fs_hint" != x ]; then
echo "set root='$fs_hint'"
fi
# Try to find filesystem label first
if [ "x${GRUB_DISABLE_UUID}" != "xtrue" ] && label="`"${grub_probe}" --device $@ --target=fs_label 2> /dev/null`"; then
hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints=
if [ "x$hints" != x ]; then
echo "if [ x\$feature_platform_search_hint = xy ]; then"
echo " search --no-floppy --label --set=root ${hints} ${label}"
echo "else"
echo " search --no-floppy --label --set=root ${label}"
echo "fi"
else
echo "search --no-floppy --label --set=root ${label}"
fi
elif [ "x${GRUB_DISABLE_UUID}" != "xtrue" ] && fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`"; then
# If no label, fall back to UUID
hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints=
if [ "x$hints" != x ]; then
echo "if [ x\$feature_platform_search_hint = xy ]; then"
echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
echo "else"
echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}"
echo "fi"
else
echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}"
fi
fi
IFS="$old_ifs"
}
修改/etc/default/grub
,在保持#GRUB_DISABLE_LINUX_UUID=true
不变的情况下,添加一行GRUB_ENABLE_LINUX_LABEL=true
,如下所示
## 注意GRUB_DISABLE_LINUX_UUID=true这一行保持注释
#GRUB_DISABLE_LINUX_UUID=true
GRUB_ENABLE_LINUX_LABEL=true
现在即可安装grub并且生成grub.cfg了。运行如下命令,其中<esp>
表示EFI分区挂载的位置,一般为/boot
。并且请务必加上--removable
标志,否则引导会安装到UEFI固件中。并且最好不要使用自定义名称(即使用--bootloader-id
参数),会导致某些bios不引导,比如我这个surface UEFI。
grub-install --target=x86_64-efi --efi-directory=<esp> --removable --recheck
运行以下命令生成grub.cfg。
grub-mkconfig -o /boot/grub/grub.cfg
可以检查一下/boot/grub/grub.cfg
了,看看是不是uuid变成了label。也可以测试是否可以正常启动。
安全启动
目前我还没有办法在可移动设备上使用安全启动,不清楚是什么原因。可能以后有机会再折腾。
咕咕咕~