制作便携式系统维护盘

本文主要描述如何在FreeBSD系统下使用独立的USB存储设备制作便携式系统维护盘。
制作完成的系统维护盘除了包含完整的FreeBSD操作系统外,还能够实现以下主要功能:

  • 修复或安装FreeBSD
  • 引导进入其他各种LiveCD
  • 安装其他操作系统

考虑到实用及便携性需求,建议使用大小为32G、接口为USB 3.0的U盘制作(以下简称U盘)。

1. 准备分区

 

1.1 获取设备信息

插上U盘后,首先确认其设备路径:

# camcontrol devlist 
<ST31000528AS CC46>                at scbus0 target 0 lun 0 (ada0,pass0)
<ST31000528AS CC46>                at scbus4 target 0 lun 0 (ada1,pass1)
<ALPHACHI USB DISK>                at scbus7 target 0 lun 0 (da0,pass2)

在这里,U盘对应的设备路径为/dev/da0;由此可以获取U盘的基本信息:

# diskinfo -v /dev/da0
/dev/da0
        512             # sectorsize
        31610372096     # mediasize in bytes (29G)
        61739008        # mediasize in sectors
        0               # stripesize
        0               # stripeoffset
        3843            # Cylinders according to firmware.
        255             # Heads according to firmware.
        63              # Sectors according to firmware.
        1292621180710063        # Disk ident.

这里需要注意sectorsize与stripesize的数值:前者为逻辑扇区大小,后者为物理扇区大小,两者单位均为字节;而只有stripesize为4096的设备在分区时才需要设置4K对齐。

1.2 创建分区

有了这些信息,即可开始分区:

# gpart destroy -F /dev/da0         清除U盘之前的分区信息
da0 destroyed
# gpart create -s MBR /dev/da0      创建新的MBR分区表
da0 created
# gpart add -t fat32 -s 4g da0      添加一个大小为4GB的FAT32分区    
da0s1 added
# gpart add -t freebsd da0          剩余分区将用于安装FreeBSD
da0s2 added
# gpart create -s BSD /dev/da0s2    在剩余分区上创建新的BSD分区表
da0s2 created
# gpart add -t freebsd-ufs da0s2    添加UFS分区
da0s2a added
# gpart show da0                    查看创建的MBR分区表
=>      63  62530561  da0  MBR  (29G)
        63   8388576    1  fat32  (4G)
   8388639  54141948    2  freebsd  (25G)
  62530587        37       - free -  (18k)

# gpart show da0s2                  查看创建的BSD分区表
=>       0  54141948  da0s2  BSD  (25G)
         0  54141948      1  freebsd-ufs  (25G)0

这里需要注意两点:

  • 为了使第一个FAT32分区能够在绝大多数Windows系统下使用,应该创建MBR分区表而非GPT分区表。
  • 直接将FreeBSD安装至第二个分区上会无法引导,需要在第二个分区中嵌套一个BSD分区表。

更多有关分区的信息,详见分配磁盘空间

2. 安装引导管理器

由于FreeBSD自带的引导管理器无法满足稍后的需求,在这里需要使用GRUB 2。

2.1 安装GRUB 2

首先通过Ports安装GRUB 2:

# portsnap fetch update
...    (省略无关输出,下同)
# cd /usr/ports/sysutils/grub2/
# make install clean
...

然后将GRUB 2的引导管理器安装至U盘:

# newfs_msdos -L USB /dev/da0s1                  格式化分区并添加卷标USB以便于之后挂载
...
# mount_msdosfs /dev/da0s1 /mnt/                 这里不能使用卷标挂载,否则GRUB 2安装后会无法引导
# grub-install --root-directory=/mnt /dev/da0    安装GRUB 2的引导管理器
...

2.2 基本配置

安装完成后,创建配置文件/mnt/boot/grub/grub.cfg:

set timeout=60            引导菜单超时秒数
set pager=1               输出内容过多时自动分屏
insmod part_gpt           预读模块part_gpt以识别使用GPT分区方案的存储设备

menuentry "Continue" {    跳过GRUB 2引导管理器
    set root=(hd1)
    chainloader +1
}

menuentry "Reboot" {      重启
    reboot
}

menuentry "Shutdown" {    关机
    halt
}

目前仅需以上这些配置即可,编辑完成后执行下列命令:

# rm /mnt/boot/grub/device.map    device.map是根据当前机器自动生成的,可以删除
# mkdir /mnt/iso/                 此目录用于放置各LiveCD对应的映像文件
# umount /mnt/                    安全卸除挂载的分区

3. 安装系统

默认情况下,FreeBSD系统的安装是通过sysinstall(9.0之前)或bsdinstall(9.0开始)所开启的交互模式进行的;但在这里,直接使用分发包安装会更加方便。下面以9.1-RELEASE amd64为例具体说明。

3.1 使用分发包安装

如果之前已经下载过安装映像文件FreeBSD-9.1-RELEASE-amd64-memstick.img,那么可以从其中直接提取分发包进行安装:

# newfs -L usb -j /dev/da0s2a                             格式化分区并添加卷标usb以便于之后挂载
...                                                       -j表示为UFS文件系统开启soft updates journaling
# mount /dev/da0s2a /mnt/
# mdconfig memstick.img                                   文件memstick.img对应于之前下载的安装映像文件
md0                                                       通过mdconfig命令用其创建内存盘
# mount /dev/md0a /media/                                 挂载创建的内存盘
# tar -C /mnt/ -xvf /media/usr/freebsd-dist/base.txz      解包并写入系统文件
...                                                       作为基系统的base.txz与kernel.txz必须安装
# tar -C /mnt/ -xvf /media/usr/freebsd-dist/kernel.txz    同目录下的其他包则可以根据需要选择安装
...
# cp -Riv /media/usr/freebsd-dist/ /mnt/install/          将分发包复制到U盘以用于在其他机器上安装系统
...
# umount /media/
# mdconfig -d -u 0                                        安全移除创建的内存盘

如果还没有下载过安装映像文件,可以通过FTP直接获取需要的分发包:

# ftp -a ftp.freebsd.org    若访问速度过慢,可更换为ftp.cn.freebsd.org
...
ftp> cd pub/FreeBSD/releases/amd64/amd64/9.1-RELEASE/
250 CWD command successful.
ftp> ls
229 Entering Extended Passive Mode (|||63772|)
150 Opening ASCII mode data connection for '/bin/ls'.
total 307588
-rw-r--r--  1 1006  1006       782 Dec  4 10:10 MANIFEST
-rw-r--r--  1 1006  1006  59854248 Dec  4 10:09 base.txz
-rw-r--r--  1 1006  1006   1443284 Dec  4 10:10 doc.txz
-rw-r--r--  1 1006  1006   1117428 Dec  4 10:10 games.txz
-rw-r--r--  1 1006  1006  58045476 Dec  4 10:10 kernel.txz
-rw-r--r--  1 1006  1006   9743636 Dec  4 10:10 lib32.txz
-rw-r--r--  1 1006  1006  87926876 Dec  4 10:10 ports.txz
-rw-r--r--  1 1006  1006  96450488 Dec  4 10:10 src.txz
226 Transfer complete.
ftp> mget base.txz kernel.txz    下载基系统包,其他包可根据需要选择下载
mget base.txz [anpqy?]? a        输入a后回车以全部确认
...

有关各分发包的说明,详见介绍bsdinstall

3.2 系统配置

经过以上操作,当前系统中的/mnt/即为将来U盘系统的根目录。现在仅需做一些必要的配置即可完成安装,而其他额外的配置可以在进入新系统后再做。
1) 创建交换文件:

# dd if=/dev/zero of=/mnt/swap bs=256m count=1
...
# chmod 0600 /mnt/swap

在这里使用交换文件替代传统的交换分区。因为空间有限,与单独的交换分区相比,能够按需调整大小的交换文件会更具弹性;注意交换文件不应小于256MB。
2) 创建/mnt/boot/loader.conf并添加以下内容:

tmpfs_load="YES"    开启内存文件系统

3) 创建/mnt/etc/fstab并添加以下内容:

/dev/ufs/usb        /         ufs        rw    1    1
/dev/msdosfs/USB    /media    msdosfs    rw    0    0
tmpfs               /tmp      tmpfs      rw    0    0

4) 创建/mnt/etc/make.conf并添加以下内容:

WRKDIRPREFIX=/tmp    在内存文件系统中编译Ports;不仅能够显著提升编译速度,更能够避免对U盘不必要的读写
                     但需注意及时make clean以防止空间耗尽

5) 创建/mnt/etc/rc.conf并添加以下内容:

swapfile="/swap"    使用交换文件
powerd_enable="YES"
hostname="FreeBSD"

更多内容可以参考/etc/defaults/rc.conf。
6) 使用命令chroot /mnt/切换根目录后,通过命令tzsetup设置时区,通过命令passwd设置root密码。操作完成后退出并卸除/mnt/上挂载的分区。

3.3 添加引导信息

挂载之前的FAT32分区以编辑GRUB 2配置文件:

# mount_msdosfs /dev/msdosfs/USB /mnt/
# vi /mnt/boot/grub/grub.cfg

在grub.cfg中为U盘系统添加对应的引导菜单:

menuentry "FreeBSD" {        设置所显示的菜单名称
    set root=(hd0,2,a)       指定系统根目录所在分区
    kfreebsd /boot/loader    指定系统加载器
}

4. 安装LiveFS

虽然之前安装的系统已经完全可以实现LiveFS的功能,但在这里仍会添加一个基于mfsBSD的LiveFS,原因在于:

  • 如果U盘本身的系统出现了故障,进入此LiveFS即可进行修复
  • mfsBSD能够被完全读入内存,非常适合大批量本地或远程部署FreeBSD

安装此LiveFS的操作非常简单,首先下载对应版本的mfsBSD映像文件并将其复制到/mnt/iso/,然后在/mnt/boot/grub/grub.cfg中添加对应的引导菜单:

menuentry "LiveFS" {
    loopback loop (hd0,1)/iso/mfsbsd-9.1-RELEASE-amd64.iso    使用loopback功能将ISO文件“模拟”为分区(loop)
    kfreebsd (loop)/boot/kernel/kernel.gz                     由于系统被读入内存,因此启动完成后可直接拔掉U盘
    kfreebsd_module (loop)/mfsroot.gz type=mfs_root
}

mfsBSD登录时root密码为mfsroot,其他相关信息请参见其官方网站
[注] 目前测试发现,9.1版本的iso文件使用此种方式引导某些机器时会报错,此问题修正前可暂时使用9.0版本。

5. 添加LiveCD

完整的系统及各种Ports,已经足以满足FreeBSD的维护需求,但对于其他的操作系统,可能还需要各种LiveCD作为补充。
有别于传统的刻录或dd命令写入方式,这里通过GRUB 2自带的loopback功能,能够非常容易的实现多个LiveCD共存:只要将LiveCD对应的iso文件置于/media/iso/,然后在/media/boot/grub/grub.cfg中添加引导菜单即可;而/media/位于FAT32分区,可以在任何系统下操作。
以下将列出一些常用的LiveCD所对应的引导菜单,未列出的可以在其对应的网站上查询。对于很多采用Syslinux引导的LiveCD,可能需要将其引导菜单手动转换为GRUB 2引导菜单。

5.1 独立式LiveCD

1) GParted(分区操作)

menuentry "GParted" {
    set root=(hd0,1)
    set file="/iso/gparted.iso"    将下载后的iso文件更名为gparted.iso
    loopback loop $file
    linux (loop)/live/vmlinuz boot=live config union=aufs noswap noprompt ip=frommedia toram=filesystem.squashfs findiso=$file
    initrd (loop)/live/initrd.img
}

这里更名文件的目的在于:新版本的LiveCD发布时,只要下载对应的iso文件并覆盖即可完成升级,无需再次修改引导菜单。
2) Clonezilla(磁盘镜像与克隆)

menuentry "Clonezilla" {
    set root=(hd0,1)
    set file="/iso/clonezilla.iso"
    loopback loop $file
    linux (loop)/live/vmlinuz boot=live live-config noswap nolocales edd=on nomodeset ocs_live_run=\"ocs-live-general\" ocs_live_extra_param=\"\" ocs_live_keymap=\"\" ocs_live_batch=\"no\" ocs_lang=\"\" ip=frommedia nosplash toram=filesystem.squashfs findiso=$file
    initrd (loop)/live/initrd.img
}

3) DBAN(数据擦除)

menuentry "DBAN" {
    loopback loop (hd0,1)/iso/dban.iso
    linux (loop)/DBAN.BZI nuke="dwipe"
}

5.2 集成式LiveCD

1) SystemRescueCd(基于Gentoo Linux)

menuentry "SystemRescueCd" {
    set root=(hd0,1)
    set file="/iso/systemrescuecd.iso"
    loopback loop $file
    linux (loop)/isolinux/rescue64 isoloop=$file docache setkmap=us dostartx
    #linux (loop)/isolinux/altker64 isoloop=$file nomodeset
    initrd (loop)/isolinux/initram.igz
}

2) Parted Magic OS(基于Slackware)

 
menuentry "PartedMagicOS" {
    set root=(hd0,1)
    set file="/iso/pmagic.iso"
    loopback loop $file
    linux (loop)/pmagic/bzImage edd=off load_ramdisk=1 prompt_ramdisk=0 rw loglevel=9 max_loop=256 vmalloc=320MiB iso_filename=$file
    initrd (loop)/pmagic/initrd.img
}

6. 维护实例

 

6.1 安装FreeBSD

安装FreeBSD时若无需多系统共存,强烈建议使用GPT而非MBR分区表,因为GPT不仅结构简练,而且没有2T容量的限制。以下为具体步骤:
1) 使用此U盘启动机器,选择FreeBSD菜单后以root登录。
2) 通过获取设备信息一节的方法获取硬盘信息,以下假设目标硬盘为/dev/ada0。
3) 输入gpart destroy -F /dev/ada0清空之前的分区信息,注意如果存在嵌套的子分区表(可通过命令gpart show检查)也应一并删除。
4) 输入gpart create -s GPT /dev/ada0创建新的GPT分区表。
5) 输入gpart add -t freebsd-boot -s 64k ada0添加大小为64KB的引导分区,若需要设置4K对齐可在命令中添加参数-a 4k。
6) 输入gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada0在引导分区中写入引导记录。
7) 输入gpart add -t freebsd-swap -s 4g -l swap ada0添加大小为4GB(可按需设置)的交换分区,若需要设置4K对齐可在命令中添加参数-a 4k;注意这里通过-l swap给分区添加了标签swap以便于挂载。
8) 输入gpart add -t freebsd-ufs -l sys ada0将剩余空间全部划分给系统,若需要设置4K对齐可在命令中添加参数-a 4k;注意这里通过-l sys给分区添加了标签sys以便于挂载。
9) 输入newfs -j /dev/ada0p3格式化系统分区,其中-j表示开启soft updates journaling;若为固态硬盘还可添加参数-t以开启TRIM。
10) 输入mount /dev/ada0p3 /mnt/将格式化好的系统分区挂载至/mnt/后,依次执行tar -C /mnt/ -xvf /install/base.txz与tar -C /mnt/ -xvf /install/kernel.txz安装基系统;注意/install/下的其他分发包也可根据需要酌情安装。
11) 参考系统配置一节进行必要的系统配置;因为这里已经添加了独立的交换分区,所以无需再配置交换文件,另外注意/mnt/etc/fstab应写为:

/dev/gpt/sys    /       ufs     rw    1    1
dev/gpt/swap    none    swap    sw    0    0
tmpfs           /tmp    tmpfs   rw    0    0

12) 配置完成后,重新启动并从硬盘引导,即可进入安装好的系统。

6.2 安装Linux

绝大多数Linux发行版都会提供ISO格式的LiveCD,同时支持从LiveCD安装系统;也就是说,只要通过添加LiveCD一节的方法引导至LiveCD即可。
例如,使用此U盘安装Gentoo Linux时,对应的GRUB 2引导菜单可写作:

menuentry "Install Gentoo" {
    set root=(hd0,1)
    set file="/iso/gentoo.iso"    将下载后的iso文件更名为gentoo.iso
    loopback loop $file
    linux (loop)/isolinux/gentoo root=/dev/ram0 init=/linuxrc dokeymap looptype=squashfs loop=/image.squashfs cdroot initrd=gentoo.igz isoboot=$file
    initrd (loop)/isolinux/gentoo.igz
}

使用此种方式引导个别Linux发行版所提供的LiveCD可能会出现一些问题,需要执行额外的修正操作。例如,下面的菜单用于引导openSUSEKDE LiveCD:

menuentry "openSUSE KDE LiveCD" {
    set root=(hd0,1)
    set file="/iso/opensuse-kde.iso"    将下载后的iso文件更名为opensuse-kde.iso
    loopback loop $file
    linux (loop)/boot/x86_64/loader/linux kiwidebug=1
    initrd (loop)/boot/x86_64/loader/initrd
}

但此菜单仅能引导至LiveCD的的Debug模式(命令行界面),必须继续手动输入以下命令来引导至图形界面:

# mkdir /livecd/
# mount /dev/sdb1 /mnt/
# mount -o loop /mnt/iso/opensuse-kde.iso /cdrom/
# mount -o loop /mnt/iso/opensuse-kde.iso /livecd/
# exit

6.3 安装Windows

由于GRUB 2并不能直接引导Windows安装所用的iso文件,因此需要使用另外一种方式。这里假设iso文件名为win.iso,目标硬盘为/dev/ada0,以下为具体步骤:
1) 使用独立式LiveCD一节的方法为此U盘添加GParted并引导进入。
2) 使用GParted为/dev/sda(即FreeBSD下的/dev/ada0)创建msdos分区表,然后划分出系统所在分区并格式化为ntfs,最后将其flag设置为boot。
3) 重启并引导进入U盘上的FreeBSD系统,使用Ports安装p7zip与fusefs-ntfs。
4) 挂载之前创建的Windows系统分区并写入Windows安装文件:

# kldload /usr/local/modules/fuse.ko    加载ntfs-3g所需的模块
# ntfs-3g /dev/ada0s1 /mnt/             这里假设之前创建的Windows系统所在分区为/dev/ada0s1
# 7z x win.iso -o{/mnt/}                由于绝大部分Windows安装盘均为UDF格式,因此无法使用tar解压
...

5) 重启并选择Continue菜单从目标硬盘引导后,即可正常安装Windows。
整个过程中需要注意两点:

  • 之所以使用GParted,是因为在FreeBSD中无法格式化NTFS分区(fusefs-ntfs自带的mkntfs命令格式化时会卡在99%)。
  • 一旦引导进入了Windows安装环境,系统分区下除sources文件夹外的所有内容均可删除,而安装完成后sources文件夹也可删除。

6.4 多系统共存

以上分别描述了如何单独安装FreeBSD、Linux与Windows,本节将说明怎样使用此U盘实现多系统共存。
使用传统方式在同一硬盘上安装多系统的难点在于:为了协调各系统启动管理器之间的关系,必须谨慎考虑安装的先后次序。使用此U盘安装则会简单很多:首先以任意顺序单独安装各系统,最后统一调整引导信息;除此之外,在任何时刻均可非常容易的修改甚至替换引导管理器。
以下为具体的安装步骤,最终实现的效果为:一块硬盘包括三个分区,使用FreeBSD自带的MBR启动管理器引导,F1、F2、F3分别对应于FreeBSD、Linux、Windows。
1) 执行安装FreeBSD一节的前3步以初始化目标硬盘,这里假设其为/dev/ada0,容量250GB。
2) 输入gpart create -s MBR /dev/ada0创建新的MBR分区表。
3) 输入gpart add -t freebsd -s 100g ada0添加大小为100GB的freebsd分区以安装FreeBSD,若需要设置4K对齐可在命令中添加参数-a 4k。
4) 输入gpart create -s BSD /dev/ada0s1嵌套BSD分区表后,输入gpart add -t freebsd-ufs ada0s1在其中添加freebsd-ufs分区,若需要设置4K对齐可在命令中添加参数-a 4k。
5) 输入gpart add -t linux-data -s 64g ada0添加大小为64GB的linux-data分区以安装Linux,若需要设置4K对齐可在命令中添加参数-a 4k。
6) 输入gpart add -t ntfs ada0将剩余空间划分为ntfs分区以安装Windows。
7) 使用安装Linux一节的方法在硬盘的第2个分区(即Linux下的/dev/sda2)上安装Linux。
8) 使用独立式LiveCD一节的方法为此U盘添加GParted并引导进入后,将硬盘的第3个分区(即GParted下的/dev/sda3)格式化为ntfs,并将其flag设置为boot。
9) 执行安装Windows一节的后3步以在ntfs分区上安装Windows。
10) 重启并引导进入U盘上的FreeBSD系统后,在硬盘的第1个分区上安装FreeBSD:

# newfs -L sys -j /dev/ada0s1a             格式化分区并添加卷标sys以便于之后挂载
...                                        若为固态硬盘还可添加-t以开启TRIM
# mount /dev/ada0s1a /mnt/
# tar -C /mnt/ -xvf /install/base.txz      解包并写入系统文件
...                                        作为基系统的base.txz与kernel.txz必须安装
# tar -C /mnt/ -xvf /install/kernel.txz    同目录下的其他包则可以根据需要选择安装
...

11) 参考系统配置一节进行必要的系统配置;注意为简化分区结构这里并未划分单独的交换分区,所以应按需设置交换文件(普通使用4GB即可),当然也可直接拆出freebsd-swap分区。
12) 安装FreeBSD自带的MBR启动管理器:

# gpart bootcode -b /boot/boot0 ada0     安装boot0引导管理器
bootcode written to ada0
# gpart set -a active -i 1 ada0          激活引导
active set on adaos1
# gpart bootcode -b /boot/boot ada0s1    写入bootstrap
bootcode written to ada0s1
# boot0cfg -t 182 /dev/ada0              设置引导菜单等待时间,注意数字单位为tick(即滴答,18.2滴答约为1秒)

整个过程中需要注意两点:

  • 各系统所在分区及安装顺序随意,只要最后安装启动管理器即可,另外F1、F2、F3键始终依次对应第1、2、3分区。
  • 一般硬盘的每磁道为63个扇区,MBR信息位于编号为0的首个扇区,而gpart会要求分区按照柱面对齐(不跨磁道),因此首个分区至少应跳过MBR所在磁道(第0至62扇区)从第63扇区开始,也就是说添加首个分区时需要在gpart命令中使用-b 63;对于支持4K对齐的硬盘,则应使用-b 504 -a 4k,其中504为4096/512与63的最小公倍数。

6.5 固件更新

对于以iso文件提供的固件更新,也可以使用类似的方式进行,但可能需要MEMDISK辅助(下载Syslinux分发包后将文件memdisk解压至/media/iso/)。
1) 更新Seagate硬盘Firmware(所需文件*.iso可从Seagate Download Finder页面查询并下载)

menuentry "Seagate Firmware" {
    set root=(hd0,1)
    loopback loop (hd0,1)/iso/*.iso
    linux16 /iso/memdisk
    initrd16 (loop)/*.ima;1    *.ima;1位于*.iso根目录中,具体名称可通过tar -tvf *.iso获取
}

2) 更新ThinkPad笔记本BIOS(所需文件*.iso可从ThinkPad网站查询并下载)

menuentry "ThinkPad BIOS" {
    set root=(hd0,1)
    linux16 /iso/memdisk iso    注意这里需添加引导参数iso
    initrd16 /iso/*.iso
}

3) 某些固件的更新可能仅提供了DOS方式,此时可使用FreeDOS

menuentry "FreeDOS" {
    set root=(hd0,1)
    linux16 /iso/memdisk iso     注意提前将固件更新所需的相关文件置于/media/
    initrd16 /iso/freedos.iso    引导成功后需要在安装过程中取消安装才能够进入Live模式执行固件更新
}

扩展信息

FreeBSD挂载光驱、U盘、ISO以及NTFS

挂载光驱

mount -t cd9660 /dev/acd0 /mnt

卸载光驱

umount /mnt

挂载U盘

mount -t msdos /dev/da0s1 /mnt

卸载U盘

umount /mnt

挂载ISO镜像文件

mount -t cd9660 /dev/`mdconfig -f cdimage.iso` /mnt

这一命令将使用第一个md设备来加载cdimage.iso所指明的iso文件,并将该md设备挂载在/mnt上。

卸载ISO镜像文件

umount /mnt

挂载NTFS文件系统

mount –t ntfs /dev/ad0s1 /mnt

卸载NTFS文件系统

umount /mnt