loveqianool 发表于 2012-2-20 00:04:19

将Arch GNU/Linux 安装到磁盘文件(loop)

作者的另一个:http://www.linuxsir.org/bbs/thread376534.html
用途:
1、安装到loop的所有功能:不让分区表太复杂等。。。支持将loop放于ntfs分区;
2、如果想尝试gnome3,又不会当工作系统, 可以将gnome3安装到changes loop文件中, 不想用gnome3的时候,删除对应loop文件,彻底。。。
3、也可以将修改保存到内存,这样就实现了硬盘上的live系统功能,“只读”, 重启,修改消失,不产生任何危害。。。

原帖:http://www.linuxsir.org/bbs/thread375524.html

修订记录:
1. 2011-03-18 木仓花axlrose的指点下,响应修改,功能加强。。。

用途:
1、多系统爱好者(比如俺),不希望磁盘分区太复杂,但又想使用多系统;
2、为测试系统方便;
3、方便删除系统(删除一个文件,修改启动配置);
4、可以做成类似PE的ROM系统;
。。。
还可以发展更多。。。

背景:
1、GRUB2 bootloader 已经支持loop设备启动(不知道其他的支持得如何);
2、 Arch GNU/Linux 官方的启动脚本无法从loop设备启动

实现的效果: 启动文件中存放的Arch GNU/Linux

实现步骤:

1、 创建loop文件

代码:dd if=/dev/zero of=/mnt/sda9/Arch/Arch-i686.img bs=1M count=3500创建一个3.5GB大小的磁盘文件Arch-i686.img 存放到 /mnt/sda9/Arch 目录下

2、 建立文件系统

代码:mkfs.reiserfs /mnt/sda9/Arch/Arch-i686.img这里只用reiserfs, 要看bootloader的支持程度, 本打算用btrfs的,结果用grub2-btrfs测试启动不成功
ext2 ext3 ext4 reiserfs 应该是支持的, 很盼望将来grub2-btrfs能完美支持btrfs的loop设备

3、安装(移植)系统到磁盘文件

代码:sudo mount /mnt/sda9/Arch/Arch-i686.img /tmp/install安装: 不赘述, 很多文档介绍

移植现有Arch GNU/Linux 系统:

代码:sudo tar cvpf - / --exclude=/mnt --exclude=/media --exclude=/sys \
      --exclude=/proc --exclude=/var/abs --exclude=/var/cache/pacman/pkg \
      --exclude=/var/lib/pacman/sync | sudo tar xvpf - -C /tmp/install4、修改相关配置

代码:sudo mkdir /tmp/install/sys修改fstab (/tmp/install/etc/fstab),将挂载/的那行改为

代码:/dev/loop0          /            reiserfs          defaults0    15、修改启动内核和loop设备的系统

这个就是重中之重了, 因为目前Arch 官方的启动脚本不支持。 这里就添加一个hook来实现挂在loop设备

1) 新建 /tm/install/lib/initcpio/hooks/automount 内容:
-----------2011-03-22--- 更新 官方模式,可以不用修改init
------------2011-03-18-- 在木仓花的建议下修改, 功能更强大
代码:run_hook ()
{
    if [ "x$loopfile" != "x" ]; then
      mount_handler="loop_mount_handler"
    fi
}

# $1 /new_root
loop_mount_handler ()
{
    # 启动参数指定 real_root=loop=/dev/sda1 loopfile=Arch/archlive.disk
    # 或者指定 real_root=loop=/dev/disk/by-label/C loopfile=Arch/archlive.disk(label有中文得时候会出错)
    # 或者指定 real_root=loop=/dev/disk/by-uuid/047C-F52A loopfile=Arch/archlive.disk
    #            上面的例子中"sda1""C""047C-F52A" 根据具体情况对应替代,或者用*花建议得grub2自动探测
    #echo "run automount hook begin"

    if [ "x$1" = "x" ]; then
      UNION="/new_root"
    else
      UNION="$1"
    fi

    # 保险点, 根据Arch目前风格,再检测、创建目录
    if [ "x$HOST" = "x" ]; then HOST="/host"; fi
    if [ ! -d $HOST ]; then mkdir -p $HOST; fi
    if [ ! -d $UNION ]; then mkdir -p $UNION; fi

    case ${real_root} in loop\=*)
      loop=${real_root/loop=}
      case $loop in *by-uuid*)
                if [ ! -e $loop ]; then
                        loop_lowercase="$(dirname $loop)/$(echo $(basename $loop) | tr [:upper:] [:lower:])"
                        loop_uppercase="$(dirname $loop)/$(echo $(basename $loop) | tr [:lower:] [:upper:])"
                        if [ -e ${loop_lowercase} ]; then
                              loop="${loop_lowercase}"
                        elif [ -e ${loop_uppercase} ]; then
                              loop="${loop_uppercase}"
                        fi
                fi
                ;;
      esac
      if [ -e $loop ]; then
                fstype=$(blkid -u filesystem -o value -s TYPE -p "${loop}")
                fsopt="-t $fstype"
                MOUNT="mount"
                if [ "${readwrite}" = "no" ]; then rwopt="ro"; else rwopt="rw"; fi
                case $fstype in
                        ntfs)MOUNT="mount.ntfs-3g"
                              rwopt="rw"
                              fsopt=""
                              ;;
                        vfat)rwopt="rw"
                        ;;
                        squashfs|iso9660|udf) rwopt="ro"
                        ;;
                        esac
                if [ "x$mountopts" != "x" ]; then
                        mountopts="-o $mountopts,$rwopt"
                else
                        mountopts="-o $rwopt"
                fi
                $MOUNT $fsopt $mountopts $loop$HOST

                if [ -f $HOST/$loopfile ]; then
                        loopfile="$HOST/$loopfile"
                        fstype=$(blkid -u filesystem -o value -s TYPE -p "${loopfile}")
                        if [ "${fstype}" = "squashfs" ]; then rwopt="ro"; fi
                        #echo "mount -t $fstype -o loop,$rwopt $loopfile $UNION"
                        mount -t $fstype -o loop,$rwopt $loopfile $UNION
                            if [ $? -eq 0 ] ; then
                              echo "mkdir -p $UNION$HOST"
                                    mkdir -p $UNION$HOST
                              # 将存放loop的分区挂载到目标系统的/host目录下,跟wubi的处理方式相同
                              #echo "mount -o bind $HOST $UNION$HOST"
                              mount -o bind $HOST $UNION$HOST
                              MOUNTED=1
                            else
                              echo " mount -t $fstype -o loop,$rwopt $loopfile $UNIONerror"
                            fi
                        else
                            echo "$HOST/$loopfileis not file"
                fi
      else
                echo "${loop} not exist!"
      fi
      ;;
      esac
    #echo "run automount hook end"
}随便写的, 快速实现需要的功能就可以了

2) 新建文件 /tmp/install/lib/initcpio/install/automount 内容如下:
代码:install ()
{
    MODULES=" $(checked_modules "/usb/host" | grep -ve "_cs" -e "sl811-hcd" -e "isp116x-hcd")"

    MODULES=$(echo ${MODULES}) #trim whitespace
    if [ -n "${MODULES}" ]; then
      MODULES="${MODULES} usb_storage sd_mod sr_mod"
      MODULES="${MODULES} $(checked_modules "drivers/usb/storage/ums-*")"
    fi
    MODULES="${MODULES} nls_utf8 cp936"
    BINARIES="blkid mount.ntfs-3g tr"
    FILES=""
    SCRIPT="automount"
}

help ()
{
cat<<HELPEOF
This hook auto mount the root device base on cmdline.
Can support:
      1. Boot from normal harddisk or USB disk;
      2. Boot from CD-ROM or DVD-ROM;
      3. Boot from loop device file (made by dd or other tools);
      4. Boot from squashfs files;
...
HELPEOF
}3) 修改 /tmp/install/etc/mkinitcpio.conf
在MODULES 中加入loop
在HOOKS最后加入 automount
代码:HOOKS="base udev autodetect pata scsi sata filesystems automount"4) ----2011-03-22 新automount脚本不需要改init 。。。


5) 重新创建内核镜像
代码:          sudo mount -o bind /sys /tmp/install/sys
          sudo chroot /tmp/install mkinitcpio -p kernel26到现在为止,磁盘文件准备完成

6、 配置启动

有几种方式:
1) 直接grub2 启动
2) ntldr --> g2ldr 来启动
3) grub --> grub2 启动
。。。 还有好几种

我用的方法2),需要制作g2ldr (不赘述,有相关文档介绍)
grub2 启动配置文件 grub.cfg 启动loop 设备项内容:

--------------2011-03-18---木仓花修改、加强如下, 可以自动搜索。。。 使用卷标、UUID。。。
代码:menuentry "Arch i686 (on loop 虚拟盘)" {
      insmod part_msdos
      insmod reiserfs
      insmod loopback

      #set img_label=winxp    #指定分区卷标label时使用
      set img_file=Arch/Arch-i686.img#设定查找标的
      search --file --no-floppy --set=img_root /$img_file    #直接搜索loop文件
      #search --label --no-floppy --set=img_root $img_label#查找指定分区卷标label方式
      #loopback loop0 (hd0,msdos9)/$img_file      #直接指定loop文件位置
      probe $img_root -l --set=img_label          #探测分区卷标label ,目标label 不能有中文等无法识别的字符
      #probe $img_root -u --set=img_root_uuid    #探测uuid 但测试发现因为大小写问题导致linux的by-uuid值不匹配
      loopback loop0 ($img_root)/$img_file
      set root=(loop0)
      linux /boot/vmlinuz26 real_root=loop=/dev/disk/by-label/$img_label loopfile=$img_filequiet
      #linux /boot/vmlinuz26 real_root=loop=/dev/disk/by-uuid/$img_root_uuid loopfile=$img_filequiet
      # 此处还可以用if等判断, 来灵活使用label或者uuid, 欢迎高手指导
      initrd /boot/kernel26-fallback.img
}重新启动即可。


后话:

1、 启动脚本automount 稍作变化, 可以扩展出更多更强的功能, 比如从squashfs 启动, 再挂载可写分区保存。。。 或者直接挂载内存做成类似PE的rom系统。。。

2、。。。


在此抛砖引玉了, 欢迎探讨。。。

[ 本帖最后由 loveqianool 于 2012-2-27 21:10 编辑 ]

zhangthe9 发表于 2012-2-20 16:20:50

这个果断要支持
回家有空就试下
ARCH 我也用的

2011niumao 发表于 2013-11-16 10:11:31

很好的老帖。被我百度出来了。

carbonjiao 发表于 2014-2-19 14:17:28

哈   居然把我的好老的帖子搞出来了!!!!!!!!

a__gu 发表于 2015-7-18 13:29:44

好东西啊,好久没来了。。。。。。。
页: [1]
查看完整版本: 将Arch GNU/Linux 安装到磁盘文件(loop)