LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 7604|回复: 78

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

[复制链接]
发表于 2011-2-25 12:04:40 | 显示全部楼层 |阅读模式
修订记录:
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文件
  1. dd if=/dev/zero of=/mnt/sda9/Arch/Arch-i686.img bs=1M count=3500
复制代码
      创建一个3.5GB大小的磁盘文件Arch-i686.img 存放到 /mnt/sda9/Arch 目录下

2、 建立文件系统

     
  1. mkfs.reiserfs /mnt/sda9/Arch/Arch-i686.img
复制代码

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

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

     
  1. sudo mount /mnt/sda9/Arch/Arch-i686.img /tmp/install  
复制代码

       安装:  不赘述, 很多文档介绍

       移植现有Arch GNU/Linux 系统:

      
  1. sudo tar cvpf - / --exclude=/mnt --exclude=/media --exclude=/sys \
  2.        --exclude=/proc --exclude=/var/abs --exclude=/var/cache/pacman/pkg \
  3.        --exclude=/var/lib/pacman/sync | sudo tar xvpf - -C /tmp/install
复制代码

4、修改相关配置

     
  1. sudo mkdir /tmp/install/sys
复制代码

      修改fstab   (/tmp/install/etc/fstab),将挂载/的那行改为   

     
  1. /dev/loop0          /             reiserfs          defaults   0    1
复制代码

5、修改启动内核和loop设备的系统

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

      1) 新建 /tm/install/lib/initcpio/hooks/automount  内容:
-----------2011-03-22--- 更新 官方模式,可以不用修改init
------------2011-03-18-- 在木仓花的建议下修改, 功能更强大
  1. run_hook ()
  2. {
  3.     if [ "x$loopfile" != "x" ]; then
  4.         mount_handler="loop_mount_handler"
  5.     fi
  6. }
  7. # $1 /new_root
  8. loop_mount_handler ()
  9. {
  10.     # 启动参数指定 real_root=loop=/dev/sda1 loopfile=Arch/archlive.disk
  11.     # 或者指定 real_root=loop=/dev/disk/by-label/C loopfile=Arch/archlive.disk   (label有中文得时候会出错)
  12.     # 或者指定 real_root=loop=/dev/disk/by-uuid/047C-F52A loopfile=Arch/archlive.disk
  13.     #               上面的例子中"sda1"  "C"  "047C-F52A" 根据具体情况对应替代,或者用*花建议得grub2自动探测
  14.     #echo "run automount hook begin"
  15.     if [ "x$1" = "x" ]; then
  16.         UNION="/new_root"
  17.     else
  18.         UNION="$1"
  19.     fi
  20.     # 保险点, 根据Arch目前风格,再检测、创建目录
  21.     if [ "x$HOST" = "x" ]; then HOST="/host"; fi
  22.     if [ ! -d $HOST ]; then mkdir -p $HOST; fi
  23.     if [ ! -d $UNION ]; then mkdir -p $UNION; fi
  24.     case ${real_root} in loop\=*)
  25.         loop=${real_root/loop=}
  26.         case $loop in *by-uuid*)
  27.                 if [ ! -e $loop ]; then
  28.                         loop_lowercase="$(dirname $loop)/$(echo $(basename $loop) | tr [:upper:] [:lower:])"
  29.                         loop_uppercase="$(dirname $loop)/$(echo $(basename $loop) | tr [:lower:] [:upper:])"
  30.                         if [ -e ${loop_lowercase} ]; then
  31.                                 loop="${loop_lowercase}"
  32.                         elif [ -e ${loop_uppercase} ]; then
  33.                                 loop="${loop_uppercase}"
  34.                         fi
  35.                 fi
  36.                 ;;
  37.         esac
  38.         if [ -e $loop ]; then
  39.                 fstype=$(blkid -u filesystem -o value -s TYPE -p "${loop}")
  40.                 fsopt="-t $fstype"
  41.                 MOUNT="mount"
  42.                 if [ "${readwrite}" = "no" ]; then rwopt="ro"; else rwopt="rw"; fi
  43.                 case $fstype in
  44.                         ntfs)  MOUNT="mount.ntfs-3g"
  45.                                 rwopt="rw"
  46.                                 fsopt=""
  47.                                 ;;
  48.                         vfat)   rwopt="rw"
  49.                         ;;
  50.                         squashfs|iso9660|udf) rwopt="ro"
  51.                         ;;
  52.                         esac
  53.                 if [ "x$mountopts" != "x" ]; then
  54.                         mountopts="-o $mountopts,$rwopt"
  55.                 else
  56.                         mountopts="-o $rwopt"
  57.                 fi
  58.                 $MOUNT $fsopt $mountopts $loop  $HOST
  59.                 if [ -f $HOST/$loopfile ]; then
  60.                         loopfile="$HOST/$loopfile"
  61.                         fstype=$(blkid -u filesystem -o value -s TYPE -p "${loopfile}")
  62.                         if [ "${fstype}" = "squashfs" ]; then rwopt="ro"; fi
  63.                         #echo "mount -t $fstype -o loop,$rwopt $loopfile $UNION"
  64.                         mount -t $fstype -o loop,$rwopt $loopfile $UNION
  65.                             if [ $? -eq 0 ] ; then
  66.                                 echo "mkdir -p $UNION$HOST"
  67.                                        mkdir -p $UNION$HOST
  68.                                 # 将存放loop的分区挂载到目标系统的/host目录下,跟wubi的处理方式相同
  69.                                 #echo "mount -o bind $HOST $UNION$HOST"
  70.                                 mount -o bind $HOST $UNION$HOST
  71.                                 MOUNTED=1
  72.                             else
  73.                                 echo " mount -t $fstype -o loop,$rwopt $loopfile $UNION   error"
  74.                             fi
  75.                         else
  76.                             echo "$HOST/$loopfile  is not file"
  77.                 fi
  78.         else
  79.                 echo "${loop} not exist!"
  80.         fi
  81.         ;;
  82.         esac
  83.     #echo "run automount hook end"
  84. }
复制代码

随便写的, 快速实现需要的功能就可以了

    2) 新建文件 /tmp/install/lib/initcpio/install/automount 内容如下:
  1. install ()
  2. {
  3.     MODULES=" $(checked_modules "/usb/host" | grep -ve "_cs" -e "sl811-hcd" -e "isp116x-hcd")"
  4.     MODULES=$(echo ${MODULES}) #trim whitespace
  5.     if [ -n "${MODULES}" ]; then
  6.         MODULES="${MODULES} usb_storage sd_mod sr_mod"
  7.         MODULES="${MODULES} $(checked_modules "drivers/usb/storage/ums-*")"
  8.     fi
  9.     MODULES="${MODULES} nls_utf8 cp936"
  10.     BINARIES="blkid mount.ntfs-3g tr"
  11.     FILES=""
  12.     SCRIPT="automount"
  13. }
  14. help ()
  15. {
  16. cat<<HELPEOF
  17.   This hook auto mount the root device base on cmdline.
  18.   Can support:
  19.         1. Boot from normal harddisk or USB disk;
  20.         2. Boot from CD-ROM or DVD-ROM;
  21.         3. Boot from loop device file (made by dd or other tools);
  22.         4. Boot from squashfs files;
  23.    ...
  24. HELPEOF
  25. }
复制代码
    3) 修改 /tmp/install/etc/mkinitcpio.conf
        在MODULES 中加入loop
        在HOOKS最后加入 automount
   
  1. HOOKS="base udev autodetect pata scsi sata filesystems automount"
复制代码

    4) ----2011-03-22 新automount脚本不需要改init 。。。


    5) 重新创建内核镜像
        
  1.           sudo mount -o bind /sys /tmp/install/sys
  2.           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。。。
     
  1. menuentry "Arch i686 (on loop 虚拟盘)" {
  2.         insmod part_msdos
  3.         insmod reiserfs
  4.         insmod loopback
  5.         #set img_label=winxp    #指定分区卷标label时使用
  6.         set img_file=Arch/Arch-i686.img   #设定查找标的
  7.         search --file --no-floppy --set=img_root /$img_file     #直接搜索loop文件
  8.         #search --label --no-floppy --set=img_root $img_label   #查找指定分区卷标label方式
  9.         #loopback loop0 (hd0,msdos9)/$img_file      #直接指定loop文件位置
  10.         probe $img_root -l --set=img_label          #探测分区卷标label ,目标label 不能有中文等无法识别的字符
  11.         #probe $img_root -u --set=img_root_uuid     #探测uuid 但测试发现因为大小写问题导致linux的by-uuid值不匹配
  12.         loopback loop0 ($img_root)/$img_file
  13.         set root=(loop0)
  14.         linux /boot/vmlinuz26 real_root=loop=/dev/disk/by-label/$img_label loopfile=$img_file  quiet
  15.         #linux /boot/vmlinuz26 real_root=loop=/dev/disk/by-uuid/$img_root_uuid loopfile=$img_file  quiet
  16.         # 此处还可以用if等判断, 来灵活使用label或者uuid, 欢迎高手指导
  17.         initrd /boot/kernel26-fallback.img
  18. }
复制代码

重新启动即可。


后话:

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

2、。。。


在此抛砖引玉了, 欢迎探讨。。。
 楼主| 发表于 2011-2-25 12:11:29 | 显示全部楼层


  1. $ df
  2. 文件系统                 1K-块      已用      可用 已用% 挂载点
  3. udev                     10240       260      9980   3% /dev
  4. /dev/loop0             3583884   1814712   1769172  51% /
  5. /dev/sda9                10240       260      9980   3% /dev/sda9
  6. shm                     509940       388    509552   1% /dev/shm
  7. /dev/sda6             25205252   8516996  15407880  36% /mnt/sda6
  8. /dev/sda9             81920884   9064008  72856876  12% /mnt/sda9
  9. /dev/sda10            84453672  38227280  46226392  46% /mnt/sda10
  10. /dev/loop1             1535948    702852    833096  46% /mnt/cxoffice
  11. /dev/sda7             25205252   2133768  21791108   9% /mnt/sda7
  12. /dev/sda1             15751700  11893804   3857896  76% /mnt/sda1

复制代码
回复 支持 反对

使用道具 举报

发表于 2011-2-25 12:14:34 | 显示全部楼层
这个文章有技术性,也是我一直想要学习的,我以前就想过有没有办法实现类似于Wubi的效果,留个脚印。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-2-25 12:30:35 | 显示全部楼层
前几天看了wubi的代码, 功能很多arch 用不上,希望高手修改。。。
回复 支持 反对

使用道具 举报

发表于 2011-2-25 13:01:15 | 显示全部楼层
太棒了,准备试试
到时弄好了的境像直接拷到其他机子的C盘上去,就不用老是用liveusb启动了
回复 支持 反对

使用道具 举报

发表于 2011-2-25 14:09:45 | 显示全部楼层
如果这个img文件放在ntfs分区上会是什么效果?读写速度怎么样?ntfs都写速度可是非常非常慢。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-2-25 14:18:18 | 显示全部楼层
放在ntfs山也可以, 没太大差别, ntfs-3g  挂载速度还可以

我最开始就是放在ntfs 分区上的


但有点, 如果出现强行关机,下次就可能无法启动了,提示需要windows CKDSK。。。 (不过我只测试了内核中默认支持的ntfs挂载)

如果用fuse ntfs-3g 可能会不同  

(wubi安装的deepin linux 就在ntfs分区, 用起来很不错的)
回复 支持 反对

使用道具 举报

发表于 2011-2-25 15:57:33 | 显示全部楼层
mark一下
说不定什么时候用得上
回复 支持 反对

使用道具 举报

发表于 2011-2-25 17:28:57 | 显示全部楼层
技术贴啊,支持一下,以后可能用的到。
回复 支持 反对

使用道具 举报

发表于 2011-2-25 19:59:26 | 显示全部楼层
收藏了,非常好的技术贴
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表