LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: carbonjiao

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

[复制链接]
发表于 2011-3-18 10:26:05 | 显示全部楼层
/lib/initcpio/hooks/automount

用mount -t ntfs的话会提示找不到设置,所以换成 mount.ntfs-3g来挂载ntfs
  1. run_hook ()
  2. {
  3.     # 启动参数指定 real_root=loop=/dev/sda1 loopfile=Arch/archlive.disk
  4.     echo "run automount hook begin"
  5.     case ${real_root} in loop\=*)
  6.         loop=${real_root/loop=}
  7.     echo "loop=${loop}"
  8.     echo "loopfile=${loopfile}"
  9.     echo "HOST=${HOST}"
  10.         echo "UNION=$UNION"
  11.         if [ -e $loop ]; then
  12.                 fstype=$(blkid -u filesystem -o value -s TYPE -p "${loop}")
  13.                 if [ "${readwrite}" = "no" ]; then rwopt="ro"; else rwopt="rw"; fi
  14.                 if [ "$fstype" = "ntfs" ] ; then
  15.             echo "mount.ntfs-3g -o $rwopt $loop  $HOST"
  16.             mount.ntfs-3g -o $rwopt $loop  $HOST
  17.         else
  18.             echo "mount -t $fstype -o $rwopt $loop $HOST"
  19.             mount -t $fstype -o $rwopt $loop $HOST
  20.                 fi
  21.                 if [ -f $HOST/$loopfile ]; then
  22.                         loopfile="$HOST/$loopfile"
  23.                         fstype=$(blkid -u filesystem -o value -s TYPE -p "${loopfile}")
  24.                         if [ "${fstype}" = "squashfs" ]; then rwopt="ro"; fi
  25.                         echo "mount -t $fstype -o loop,$rwopt $loopfile $UNION"
  26.                         mount -t $fstype -o loop,$rwopt $loopfile $UNION
  27.             if [ $? -eq 0 ] ; then
  28.                 echo "mkdir -p $UNION$HOST"
  29.                 mkdir -p $UNION$HOST
  30.                 echo "mkdir -p $UNION$loop"
  31.                 mkdir -p $UNION$loop
  32.                 echo "mount -o bind $HOST $UNION$loop"
  33.                 mount -o bind $HOST $UNION$loop
  34.                 MOUNTED=1
  35.             else
  36.                 echo " mount -t $fstype -o loop,$rwopt $loopfile $UNION   error"
  37.             fi
  38.         else
  39.             echo "$HOST/$loopfile  is not file"
  40.                 fi
  41.     else
  42.         echo "${loop} not exist!"
  43.         fi
  44.         ;;
  45.         esac
  46.     echo "run automount hook end"
  47. }
复制代码

/lib/initcpio/hooks/automount
  1. install ()
  2. {
  3.     add_device /lib/udev/devices/loop0 b 7 0
  4.     BINARIES="blkid mount.ntfs-3g"
  5.     FILES=""
  6.     SCRIPT="automount"
  7. }
  8. help ()
  9. {
  10. cat<<HELPEOF
  11.   This hook auto mount the root device base on cmdline.
  12.   Can support:
  13.         1. Boot from normal harddisk or USB disk;
  14.         2. Boot from CD-ROM or DVD-ROM;
  15.         3. Boot from loop device file (made by dd or other tools);
  16.         4. Boot from squashfs files;
  17.    ...
  18. HELPEOF
  19. }
复制代码

grub2 的引导参数
  1. menuentry "Arch i686 (on loop 虚拟盘C盘)" {
  2.         insmod part_msdos
  3.         insmod reiserfs
  4.         insmod loopback
  5.         #loopback loop0 (hd0,msdos9)/Arch/Arch-i686.img
  6.         loopback loop0 (hd0,1)/Arch/Arch-i686.img
  7.         set root=(loop0)
  8.         linux /boot/vmlinuz26 real_root=loop=/dev/sda1 loopfile=Arch/Arch-i686.img  quiet
  9.         initrd /boot/kernel26-fallback.img
  10. }
复制代码

/lib/initcpio/init中
之前没有加上 mkdir -p $UNION 所以没挂成功
  1. init 中设置
  2. export HOST="/host"
  3. export UNION="/new_root"
  4. mkdir -p $HOST
  5. mkdir -p $UNION
  6. # 挂载根成功后 MOUNTED=1
  7. export MOUNTED="0"
  8. # 如果hook已经完成root 则跳过Arch 默认的root侦测
  9. if [ "$MOUNTED" = "0" ]; then ${mount_handler} $UNION; fi
复制代码
  1. $ diff /lib/initcpio/init /tmp/img/lib/initcpio/init -u
  2. --- /lib/initcpio/init  2011-02-23 05:49:05.000000000 +0800
  3. +++ /tmp/img/lib/initcpio/init  2011-03-18 11:27:16.000000000 +0800
  4. @@ -26,6 +26,11 @@
  5. export init=""
  6. echo "/sbin/modprobe" > /proc/sys/kernel/modprobe
  7. +export HOST="/host"
  8. +export UNION="/new_root"
  9. +mkdir -p $HOST
  10. +mkdir -p $UNION
  11. +
  12. # set default mount handler
  13. mount_handler="default_mount_handler"
  14. @@ -120,8 +125,9 @@
  15. fi
  16. # Mount root at /new_root
  17. -mkdir -p /new_root
  18. -${mount_handler} /new_root
  19. +#mkdir -p /new_root
  20. +#${mount_handler} /new_root
  21. +if [ "$MOUNTED" = "0" ]; then ${mount_handler} $UNION; fi
  22. [ -z "${init}" ] && init="/sbin/init"
  23. if [ "$(stat -c %D /)" = "$(stat -c %D /new_root)" ]; then
复制代码

以上设置在vfat, ntfs 下测试成功,使用grub2和 grub24dos 下都能引导

等老焦发布个官方模块方式的
回复 支持 反对

使用道具 举报

发表于 2011-3-18 11:10:46 | 显示全部楼层
用了楼上的脚本,Boot到将镜像文件mount到/new_root后就无动作了,不知道是什么原因。
回复 支持 反对

使用道具 举报

发表于 2011-3-18 12:38:40 | 显示全部楼层
分享一下刚折腾grub2自动搜索并将分区参数传递给kernel的方法
以下用到的是label, 因为看了grub2源代码发现有个probe的命令很强悍
probe支持uuid, label方式,我用的是label,因为试了uuid结果取的值是16进制的小写,
当引导后进入linux检测 /dev/disk/by-uuid/时,是大写的16进制,引导失败
如果全转为大写的话,有的分区又是用的小写,有搞定的高手别忘了分享一下
ls -l /dev/disk/by-uuid/  就出来了,不知道linux是用什么方式来处理的
  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     #搜索指定文件
  8.     #search --label --no-floppy --set=img_root $img_label   #固定label方式
  9.         #loopback loop0 (hd0,msdos9)/$img_file
  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.         initrd /boot/kernel26-fallback.img
  17. }
复制代码
楼上,我检测出来少了new_root目录,是通过ls , echo 输出信息来找到的,你也可以试试,相信就是少了个目录之类的小问题
回复 支持 反对

使用道具 举报

发表于 2011-3-18 12:46:23 | 显示全部楼层
参具体点说吗?手工操作的话,要怎么做?
我参考过Wubi的Ubuntu,它的/host是建立在目录树顶层的。
我要在Arch的这个镜像里建立/host/new_root?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-3-18 13:07:30 | 显示全部楼层
Post by axlrose;2131400
分享一下刚折腾grub2自动搜索并将分区参数传递给kernel的方法
以下用到的是label, 因为看了grub2源代码发现有个probe的命令很强悍
probe支持uuid, label方式,我用的是label,因为试了uuid结果取的值是16进制的小写,
当引导后进入linux检测 /dev/disk/by-uuid/时,是大写的16进制,引导失败
如果全转为大写的话,有的分区又是用的小写,有搞定的高手别忘了分享一下
ls -l /dev/disk/by-uuid/  就出来了,不知道linux是用什么方式来处理的


适合uuid的 hooks/automount
  1. run_hook ()
  2. {
  3.     # 启动参数指定 real_root=loop=/dev/sda1 loopfile=Arch/archlive.disk
  4.     # 或者指定 real_root=loop=/dev/disk/by-label/C loopfile=Arch/archlive.disk   (label有中文得时候会出错)
  5.     # 或者指定 real_root=loop=/dev/disk/by-uuid/047C-F52A loopfile=Arch/archlive.disk
  6.     #               上面的例子中"sda1"  "C"  "047C-F52A" 根据具体情况对应替代,或者用*花建议得grub2自动探测
  7.     echo "run automount hook begin"
  8.     # 保险点, 根据Arch目前风格,再检测、创建目录
  9.     if [ "x$HOST" = "x" ]; then HOST="/host"; fi
  10.     if [ -d $HOST ]; then mkdir -p $HOST; fi
  11.     if [ "x$UNION" = "x" ]; then UNION="/new_root"; fi
  12.     if [ -d $UNION ]; then mkdir -p $UNION; fi
  13.     case ${real_root} in loop\=*)
  14.         loop=${real_root/loop=}
  15.         echo "loop=${loop} loopfile=${loopfile} HOST=${HOST} UNION=$UNION"
  16.         case $loop in *by-uuid*)
  17.                 if [ ! -e $loop ]; then
  18.                         loop_lowercase="$(dirname $loop)/$(echo $(basename $loop) | tr [:upper:] [:lower:])"
  19.                         loop_uppercase="$(dirname $loop)/$(echo $(basename $loop) | tr [:lower:] [:upper:])"
  20.                         if [ -e ${loop_lowercase} ]; then
  21.                                 loop="${loop_lowercase}"
  22.                         elif [ -e ${loop_uppercase} ]; then
  23.                                 loop="${loop_uppercase}"
  24.                         fi
  25.                 fi
  26.                 ;;
  27.         esac
  28.         if [ -e $loop ]; then
  29.                 fstype=$(blkid -u filesystem -o value -s TYPE -p "${loop}")
  30.                 if [ "${readwrite}" = "no" ]; then rwopt="ro"; else rwopt="rw"; fi
  31.                 if [ "$fstype" = "ntfs" ] ; then
  32.                             echo "mount.ntfs-3g -o $rwopt $loop  $HOST"
  33.                             mount.ntfs-3g -o $rwopt $loop  $HOST
  34.                 else
  35.                             echo "mount -t $fstype -o $rwopt $loop $HOST"
  36.                             mount -t $fstype -o $rwopt $loop $HOST
  37.                 fi
  38.                 if [ -f $HOST/$loopfile ]; then
  39.                         loopfile="$HOST/$loopfile"
  40.                         fstype=$(blkid -u filesystem -o value -s TYPE -p "${loopfile}")
  41.                         if [ "${fstype}" = "squashfs" ]; then rwopt="ro"; fi
  42.                         echo "mount -t $fstype -o loop,$rwopt $loopfile $UNION"
  43.                         mount -t $fstype -o loop,$rwopt $loopfile $UNION
  44.                             if [ $? -eq 0 ] ; then
  45.                                 echo "mkdir -p $UNION$HOST"
  46.                                        mkdir -p $UNION$HOST
  47.                                 # 将存放loop的分区挂载到目标系统的/host目录下,跟wubi的处理方式相同
  48.                                 echo "mount -o bind $HOST $UNION$HOST"
  49.                                 mount -o bind $HOST $UNION$HOST
  50.                                 MOUNTED=1
  51.                             else
  52.                                 echo " mount -t $fstype -o loop,$rwopt $loopfile $UNION   error"
  53.                             fi
  54.                         else
  55.                             echo "$HOST/$loopfile  is not file"
  56.                 fi
  57.         else
  58.                 echo "${loop} not exist!"
  59.         fi
  60.         ;;
  61.         esac
  62.     echo "run automount hook end"
  63. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-3-18 13:09:44 | 显示全部楼层
Post by alpha.gu;2131401
参具体点说吗?手工操作的话,要怎么做?
我参考过Wubi的Ubuntu,它的/host是建立在目录树顶层的。
我要在Arch的这个镜像里建立/host/new_root?


之前我得疏忽漏了一句

mkdir -p $UNION

导致挂载  loop  时候出错  现在修改了, init文件类似如下:

/lib/initcpio/init

  1. #!/bin/busybox ash

  2. # Clean input/output
  3. exec > /dev/console </dev/console 2>&1

  4. # Install busybox's applets as symlinks
  5. /bin/busybox --install -s

  6. . /init_functions

  7. msg ":: Loading Initramfs"
  8. /bin/mount -t proc proc /proc -o nosuid,noexec,nodev
  9. /bin/mount -t sysfs sys /sys -o nosuid,noexec,nodev

  10. mount -o remount,rw / >/dev/null 2>&1

  11. if grep -q devtmpfs /proc/filesystems 2>/dev/null; then
  12.   /bin/mount -n -t devtmpfs udev /dev -o mode=0755,size=10M,nosuid
  13. else
  14.   /bin/mount -n -t tmpfs udev /dev -o mode=0755,size=10M,nosuid
  15.   # We don't have devtmpfs, so add the most important standard devices
  16.   /bin/mknod /dev/null c 1 3
  17.   /bin/mknod /dev/zero c 1 5
  18.   /bin/mknod /dev/console c 5 1
  19.   # /dev/mem is needed if we want to load uvesafb before triggering uevents
  20.   /bin/mknod /dev/mem c 1 1
  21. fi

  22. read CMDLINE </proc/cmdline
  23. export CMDLINE

  24. export root=""
  25. export init=""
  26. echo "/sbin/modprobe" > /proc/sys/kernel/modprobe

  27. export HOST="/host"
  28. # Mount root at $UNION
  29. export UNION="/new_root"
  30. mkdir -p $UNION
  31. mkdir -p $HOST

  32. # 挂载根成功后 MOUNTED=1
  33. export MOUNTED="0"

  34. # set default mount handler
  35. mount_handler="default_mount_handler"

  36. # if available, start udevd at this stage
  37. if [ -x /sbin/udevd ]; then
  38.     msg ":: Starting udevd..."
  39.     echo > /proc/sys/kernel/hotplug
  40.     /sbin/udevd --daemon --resolve-names=never
  41.     export udevd_running=1
  42.     msg "done."
  43. else
  44.     export udevd_running=0
  45. fi

  46. for cmd in ${CMDLINE}; do
  47.     case "${cmd}" in
  48.         \#*) break ;; # ignore everything after a # in the commandline
  49.         # The kernel passes those to the kernel on its own
  50.         [0123456Ss]) ;;
  51.         [0-9]*) ;;
  52.         single) ;;
  53.         rw) readwrite="yes" ;;
  54.         ro) readwrite="no" ;;
  55.         # only export stuff that does work with ash :)
  56.         *=*) rhs="$(echo "${cmd}" | cut -d= -f2-)"
  57.              cmd="$(echo "${cmd}" | cut -d= -f1 | sed 's|\.|_|g')"
  58.              cmd="$(echo "${cmd}" | sed 's|-|_|g')=${rhs}"
  59.              (echo "${cmd}" | grep -qe '^[0-9]') || export "${cmd}"
  60.              ;;
  61.         *)   cmd="$(echo "${cmd}" | sed 's|\.|_|g')"
  62.              cmd="$(echo "${cmd}" | sed 's|-|_|g')"
  63.              (echo "${cmd}" | grep -qe '^[0-9]') || export "${cmd}=y"
  64.              ;;
  65.     esac
  66. done

  67. if [ -n "${disablehooks}" ]; then
  68.     for d in $(echo "${disablehooks}" | sed 's|,| |g'); do
  69.         export "hook_${d}=disabled"
  70.     done
  71. fi

  72. if [ -n "${disablemodules}" ]; then
  73.     for d in $(echo "${disablemodules}" | sed 's|,| |g'); do
  74.         export "mod_${d}=disabled"
  75.     done
  76. fi

  77. if [ -n "${earlymodules}" ]; then
  78.     for m in $(echo "${earlymodules}" | sed 's|,| |g'); do
  79.         /sbin/modprobe -q ${m} > /dev/null 2>&1
  80.     done
  81. fi

  82. . /config

  83. for m in ${MODULES}; do
  84.     TST=""
  85.     eval "TST=\$mod_${m}"
  86.     if [ "${TST}" != "disabled" ]; then
  87.         /sbin/modprobe -q ${m} > /dev/null 2>&1
  88.     fi
  89. done

  90. # If rootdelay is empty or not a non-negative integer, set it to 10
  91. if [ -z "${rootdelay}" ] || ! [ "${rootdelay}" -ge 0 ]; then
  92.     export rootdelay=10
  93. fi

  94. if [ -e "/hooks" ]; then
  95.     for h in ${HOOKS}; do
  96.         TST=""
  97.         eval "TST=\$hook_${h}"
  98.         if [ "${TST}" != "disabled" ]; then
  99.             run_hook () { msg "${h}: no run function defined"; }
  100.             if [ -e "/hooks/${h}" ]; then
  101.                . /hooks/${h}
  102.                msg ":: Running Hook [${h}]"
  103.                run_hook
  104.             fi
  105.         fi
  106.     done
  107. fi

  108. if [ "${break}" = "y" ]; then
  109.     echo ":: Break requested, type 'exit' to resume operation"
  110.     launch_interactive_shell
  111. fi

  112. if [ -f "/message" ]; then
  113.     msg "$(cat /message)"
  114. fi

  115. if [ "$MOUNTED" = "0" ]; then
  116.         ${mount_handler} $UNION
  117. fi

  118. [ -z "${init}" ] && init="/sbin/init"
  119. if [ "$(stat -c %D /)" = "$(stat -c %D /new_root)" ]; then
  120.     # Nothing got mounted on /new_root. This is the end, we don't know what to do anymore
  121.     # We fall back into a shell, but the shell has now PID 1
  122.     # This way, manual recovery is still possible.
  123.     err "Failed to mount the real root device."
  124.     echo "Bailing out, you are on your own. Good luck."
  125.     echo
  126.     launch_interactive_shell --exec
  127. elif [ ! -x "/new_root${init}" ]; then
  128.     # Successfully mounted /new_root, but ${init} is missing
  129.     # The same logic as above applies
  130.     err "Root device mounted successfully, but ${init} does not exist."
  131.     echo "Bailing out, you are on your own. Good luck."
  132.     echo
  133.     launch_interactive_shell --exec
  134. fi

  135. #Special handling if udev is running
  136. udevpid=$(/bin/pidof udevd)
  137. if [ -n "${udevpid}" ]; then
  138.     # Settle pending uevents, then kill udev
  139.     /sbin/udevadm settle
  140.     /bin/kill ${udevpid} > /dev/null 2>&1
  141.     while /bin/pidof udevd >/dev/null; do
  142.         sleep 0.1
  143.     done
  144. fi

  145. mount --move /proc /new_root/proc
  146. mount --move /sys /new_root/sys
  147. mount --move /dev /new_root/dev
  148. exec /sbin/switch_root -c /dev/console /new_root ${init} "$@"


复制代码
回复 支持 反对

使用道具 举报

发表于 2011-3-18 13:42:46 | 显示全部楼层
hooks中的脚本有一处疑问,
  1. mount -o bind $HOST $UNION$loop
复制代码
是否为笔误
是不是应该为
  1. mount -o bind $HOST $UNION$HOST
复制代码
因为wubi上看到通过 /$HOST 可以访问到该分区的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-3-18 13:55:49 | 显示全部楼层
Post by axlrose;2131413
hooks中的脚本有一处疑问,
  1. mount -o bind $HOST $UNION$loop
复制代码
是否为笔误
是不是应该为
  1. mount -o bind $HOST $UNION$HOST
复制代码
因为wubi上看到通过 /$HOST 可以访问到该分区的

放loop的分区挂载到目标系统的哪个目录下无一定之规,
我最开始的想法是, loop放在/dev/sda1 则挂载到目标系统的 /sda1  下

鉴于木仓花axlrose的建议, 使用wubi的处理方式, 挂载到目标系统的 /host下
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-3-18 14:40:58 | 显示全部楼层
刚才跟木仓花又讨论了下, 这个还蛮有搞头得, 嘎嘎。。。

1. 加密loop, 保证数据安全;
2. 将loop放在U盘(任意fat ntfs分区,随便跑。。。);
3. 加强automount, 系统部分采用sqfs loop 只读挂载,数据等 其它loop可写挂载。。。

。。。

我cao  bbs.archlinux.org  Installation 版的一个liao 管理员还说我这个完全无意义。。。  还删贴(要我发到wiki, 我说这个太简陋了,先讨论,完善下再发wiki。。。)

可能还是mailling list 中讨论好点。。。
回复 支持 反对

使用道具 举报

发表于 2011-3-18 15:05:25 | 显示全部楼层
中文maillist实在没搞头啊
俺英文太烂了,要不然的话到官方maillist去讨论,我想是有搞头的
让老外也一起来完善一下,说不定有兴趣的人把wubi给弄到archlinux上去,更方便了
回复 支持 反对

使用道具 举报

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

本版积分规则

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