将Arch Linux系统安装在可移动设备上的要点

前言

最近在折腾将arch linux安装在可移动硬盘上,将踩坑的点在此文章做记录。

fastfetch

安装系统

安装系统时最好使用虚拟机连接你的可移动设备进行安装,若用真机小心你的真机数据以及你的引导,很多发行版不能自定义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中的UUIDLABEL

当然也可以不修改,只是为了更好的识别设备。

如果你和我一样是用的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"

注意:

  1. 设置标签时swap分区或者主分区需要取消挂载,swap分区可以先使用以下命令再设置标签。而对于主分区(rootfs)只能使用livecd设置标签。
swapoff /dev/XXX
  1. EFI分区的标签最好设置为全大写字母,防止bios不兼容。

设置标签后即可修改/etc/fstab中的UUIDLABEL,修改完后如下所示。

使用如下命令即可直接使用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,将blockkeyboardhook 移动到autodetecthook 之前。这样才能在分别需要早期用户空间中不同模块的系统上启动。如下所示

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。也可以测试是否可以正常启动。

安全启动

目前我还没有办法在可移动设备上使用安全启动,不清楚是什么原因。可能以后有机会再折腾。

咕咕咕~