Linux根据磁盘的属性挂载root


Linux的2.6内核有了sysfs,可以通过这个文件系统得到系统设备的一些属性,作为使用sysfs的一个例子,我们可以修改initrd的init脚本,使得它可以根据磁盘的属性而不是bootloader中kernel的root参数来寻找并挂载root,传统中都是根据root=/dev/sdXy(hdXy)来挂载根的,写下这个sdXy或者hdXy需要用户对linux的磁盘命名很了解,一旦hda变成了hdb1(很容易发生,比如跳线或者换了主板或者磁盘插错了槽),很多人就不知所措了,我们更需要一种人性化的方式,比如root=seagate/usb等等来寻找并挂载root,有了sysfs,这些都可以在initrd的init脚本中做到。

以下是基本的sh1脚本(或者写成一个脚本函数也行):

sh1:
mount -t sysfs sys /sys
for DISK in `ls /sys/block/|grep $pref`; do               #pref为磁盘前缀,比如hd为ide磁盘,sd为scsi磁盘
    disk=`cat /sys/block/$DISK/device/model`
    if [ -n "$disk" ]; then
        if [ "${disk:0:12}" = "$type" ]; then         #type为磁盘类型,比如cf卡,dom等
            maj=`cat /sys/block/sda/dev|awk -F : '{print $1}'`
            min=$((`cat /sys/block/sda/dev|awk -F : '{print $2}'`+1)) #默认是第一个分区,当然可以在此加以判断寻找任意分区。
            mknod /dev2/device1 b $maj $min        #寻找到了设备号,创建设备
            mount -t ext3 /dev2/device1 /mnt       #挂载刚创建的设备,后面我们直接chroot到/mnt,然后exec(sbin/init)即可
            if [ "$?" -eq 0 ]; then                #成功
                flag="found"                   #设置标志
                rm -f /mnt/dev/root            #删除创建的设备
                mknod /mnt/dev/root b $maj $min #创建根文件系统中的设备,用于mount时的显式(/etc/fstab中写/dev/root)
                break                #跳出循环
            else
                echo "not found"         #测试
            fi
        else
            echo BianFen                 #测试“扁粉菜”
        fi
    fi
done

可以在initrd的init脚本中实现一个基于优先级的挂载序列,类似bios中设置启动顺序的那样,比如可以设置usb,dom卡,cf卡,sata磁盘为挂载为根的顺序,在init脚本中首先通过sh1寻找usb设备,如果找到直接将之挂为root,如果找不到则继续调用sh1寻找dom,依次类推。这样的话,即使事先不知道磁盘是hd的还是sd的,又不知道是hda1还是hdb1的情况下,只要我们只知道磁盘的一些特性(在sh1这个例子中我们使用model特性,也可以遍历device目录匹配任意属性,当然sh1的代码需要更复杂一些,这里仅仅给出思想)。

为何要修改initrd,因为很多场景都需要一份grub配置文件在多台不同机器上都能用,而这些机器的磁盘引线可能不同,比如有的机器上磁盘在hda1,而另外一些机器上就成了hdb1,这样就需要修改grub配置中kernel的root参数了,或者通过硬件跳线来解决,为了不做这些烦人的动作,索性搞一个自适应的initrd,而我们所做的仅仅是知道一些磁盘的内秉属性即可,比如一块西部数据的磁盘作为hda和hdb时都是这个牌子,不会变的,不会因机器主板的变化而变化。

相关内容