Chinaunix首页 | 论坛 | 博客
  • 博客访问: 118318
  • 博文数量: 42
  • 博客积分: 932
  • 博客等级: 准尉
  • 技术积分: 470
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-18 22:33
文章分类
文章存档

2011年(42)

分类: LINUX

2011-08-07 23:25:14

  这几天主要做了一件事,从宿主机上精简出一个10M的Linux,最初按老师的要求一步一步的做,不过还是经常出现各种问题,后来老师就要求用脚本实现,最初由6个脚本组成,再将其合成一个,经过3天得加工和完善,今天终于完成了,这也是从学习Linux到现在写的最长耗也最长的脚本了,完成后其实还是蛮有成就感的,呵呵~!虽然脚本不尽完善,里面还有很多瑕疵和缺陷,然而毕竟是自己努力了3天的结果面对345行的脚本还是挺高兴的!如果大家有兴趣的话也可以尝试下,把最初的6个脚本放在这里给大家参考下,这会儿虚拟机正在编译内核呢,所以最终的脚本明天再补上吧!这也是怎么从宿主机精简出一个小Linux的具体步骤了!
  一、写一个脚本,实现将一个硬盘中原有分区信息全部删除,并重新将其分为三个区:
1、提示用户指定要操作的磁盘;
2、提示用户接下来操作会破坏硬盘上的所有数据,并询问用户是否继续进行;形如:Continue(y/N)?
   如果用户选择继续,如果此硬盘中有分区,则抹除此硬盘上的所有分区信息(如果是仍处理挂载状态的分区,则需要先卸载);否则退出;
3、将此硬盘分为三个主分区:
  第一个主分区,50M,ext3文件系统
  第二个主分区,512M,ext3文件系统
  第三个主分区,256M,swap文件系统
要求:上面第2和第3步要求用函数实现;函数执行结束要有返回值;
  1. SPART() {
  2. dd if=/dev/zero of=$1 bs=512 count=1
  3. sleep .1
  4. echo "
  5. n
  6. p
  7. 1
  8. +50M
  9. n
  10. p
  11. 2
  12. +521M
  13. n
  14. p
  15. 3
  16. echo "
  17. n
  18. p
  19. 1
  20. +50M
  21. n
  22. p
  23. 2
  24. +521M
  25. n
  26. p
  27. 3
  28. +256M
  29. t
  30. 3
  31. 82
  32. w
  33. " | fdisk $1
  34. mke2fs -j $11
  35. mke2fs -j $12
  36. mkswap -f $13
  37. partprobe $1
  38. }
    1. read -p "please choose a disk:" UDISK
    2. fdisk -l $UDISK | grep "^\/dev"
      FENQU=`fdisk -l $UDISK | grep "^\/dev" | awk '{print $1}'`
      for I in $FENQU;do
      if mount | grep "$I"  &> /dev/null;then
       mount | grep "$I"
       else
       echo "$I is not mounted"
      fi
      done
      read -p "Next action will destory all date continue(y|N)?:" CHOICE
      case $CHOICE in
      y|Y)
      for I in $FENQU;do
      if mount | grep "$I"  &> /dev/null;then
       mount | grep "$I"
       umount $I
      fi
      done
      SPART $UDISK
      return 0
      ;;
      n|N)
      exit
      ;;
      *)
      exit
      ;;
      esac

二、写一个脚本,实现将上述步骤中创建的分区挂载至某目录:
1、写一个函数,接受两个参数,完成以下功能:  
   参数1为/boot分区对应的设备,传递至函数之后将其挂载至/mnt/boot;
   参数2为/分区对应的设备,传递至函数之后将其挂载至/mnt/sysroot;
   说明:上述的挂载点/mnt/boot和/mnt/sysroot如果事先不存在,需要先创建;如果事先存在,且已经被某设备挂载使用,则需要先卸载原来挂载的设备;
2、将第一个脚本中实现的分区1和分区2传递给些函数执行;
  1. #!/bin/bash
  2. #
  3. MYMOUNT (){
  4. if [ -d $2 ] ;then
  5. if mount | awk '{print$3}' | grep "$2" ;then
  6. fuser -km $2
  7. umount $2
  8. mount $1 $2
  9. else
  10. mount $1 $2
  11. fi
  12. else
  13. mkdir $2
  14. mount $1 $2
  15. fi
  16. }
  17. cd
  18. cd younan
  19. source fdisk.sh
  20. MYMOUNT ${UDISK}1 /mnt/boot
  21. MYMOUNT ${UDISK}2 /mnt/sysroot
  22. ~
 
 
 

三、写一个脚本,初始化rootfs
1、写一个函数,接受一个参数(参数为第二步骤中挂载的/mnt/sysroot),完成以下功能;
   1)判断/mnt/sysroot是否存在并且如果存在是否是挂载的一个独立的分区,如果是,则继续后面的操作;否则,则提示用户错误信息,而后询问是否继续;
   2)在/mnt/sysroot目录中创建如下子目录:
   boot, proc, sys, dev, home, root, etc/{rc.d,sysconfig,init.d}, bin, sbin, lib, usr/{bin,sbin,lib,include}, var/{log,run}, tmp, mnt, opt, media;
   3)将上面创建的tmp目录的权限设置为1777;
   4)创建文件/mnt/sysroot/etc/inittab,内容如下:
   id:3:initdefault:
   si::sysinit:/etc/rc.d/rc.sysinit
   5)创建文件/mnt/sysroot/etc/rc.d/rc.sysinit,内容如下:
   #!/bin/bash
   echo -e "\t\tWelcome to \033[31;1mLittle\033[0m Linux..."
  
   mount -n -o remount,rw /
   mount -n -a
  
   /bin/bash
  
   而后给此文件以执行(755)权限;
   6)创建文件/mnt/sysroot/etc/fstab,内容如下:
   /dev/sda2        /            ext3    defaults        0 0
   /dev/sda1               /boot                   ext3    defaults        0 0
   sysfs                   /sys                    sysfs   defaults        0 0
   proc                    /proc                   proc    defaults        0 0
2、执行此函数
  1. #!/bin/bash
  2. #
  3. CHROOT() {
  4. if [ -d $1 ] && df -h | grep "$1$" ;then
  5. cd $1
  6. mkdir -pv boot proc sys dev home root etc/{rc.d,sysconfig,init.d} bin sbin lib usr/{bin,sbin,lib,include} var/{log,run} tmp mnt opt media
  7. chmod 777 tmp
  8. cd /mnt/sysroot/etc
  9. touch inittab
  10. cat >> inittab <
  11. id:3:initdefault:
  12. si::sysinit:/etc/rc.d/rc.sysinit
  13. EOF
  14. cd .
  15. cd rc.d/
  16. touch rc.sysinit
  17. cat >> rc.sysinit <
  18. #!/bin/bash
  19. echo -e "\t\tWelcome to \033[31mLittle\033[0m Linux..."
  20. mount -n -o remount,rw /
  21. mount -n -a
  22. /bin/bash
  23. EOF
  24. cd .
  25. touch fastab
  26. cat >> fstab << EOF
  27. /dev/sda2 / ext3 defaults 0 0
  28. /dev/sda1 /boot ext3 defaults 0 0
  29. sysfs /sys sysfs defaults 0 0
  30. proc /proc proc defaults 0 0
  31. EOF
  32. else
  33. echo "Warning"
  34. fi
  35. }
  36. CHROOT /mnt/sysroot
四、写一个脚本,实现二进制命令及对应库文件的拷贝:
1、写一个函数,接受两个参数(参数1为要复制的命令,参数2为复制命令对应的目标位置,如/mnt/sysroot),完成以下功能:
   1)判断参数1所对应的命令是否存在;如果存在:
     取得其目录路径,及命令对应的文件的名字;
     而后将此命令复制到参数2对应的路径下,跟此命令原来的目录路径相同的子目录中;
     比如,如果参数2为/mnt/sysroot,而命令路径为/bin/ls,则需要将ls复制到/mnt/sysroot/bin目录;如果命令路径为/usr/bin/man,则需要将man复制至/mnt/sysroot/usr/bin/中去;
   2)复制命令的同时,判定此命令所依赖的库文件,而后对每一个库文件做如下操作:
     取得其目录路径,及命令对应的文件的名字;
     而后将此命令复制到参数2对应的路径下,跟此命令原来的目录路径相同的子目录中;但如果此库文件已经复制过,则不需要再次复制;
2、执行此函数;
  1. #!/bin/bash
  2. #
  3. MINGLING() {
  4. if which $1;then
  5. DR=`which $1 | grep -o "/.*" | sed -n 's/\(.*\)\/.*/\1/p'`
  6. FR=`which $1 | grep -o "/.*"`
  7. [ -d ${2}$DR ] || mkdir -pv ${2}$DR &> /dev/null
  8. [ -e ${2}$FR ]|| cp $FR ${2}$DR
  9. LIB=`ldd $FR | sed -n 's/.*\/lib\/\(.*\)/\1/gp' | awk '{print $1}'`
  10. for I in $LIB;do
  11. LDR=`ldd $FR | grep -o '/.*' | awk '{print $1}' | sed -n 's@\(/.*\)/'"$I"'@\1@gp'`
  12. [ -d ${2}$LDR ] || mkdir -pv ${2}$LDR &> /dev/null
  13. [ ! -e ${2}"$LDR"/"$LIB" ] && cp -f "$LDR"/"$I" ${2}$LDR
  14. done
  15. else
  16. echo "$1 is not exit."
  17. fi
  18. }
  19. read -p "Which command do you need:" CM
  20. read -p "Where do you want to save this conmand:" DIR
  21. MINGLING $CM $DIR
这个脚本有点儿问题就是一次只能拷贝一个命令 哈哈~!后来做过修改了,一次将我自己所要的命令全拷贝过去就是写了个循环 这里也可以写个until 或者 while 循环 提示用户当输入q时可以退出 否则就是一直拷贝自己要得命令!如:rean -p "Enter q to quit anyother command to contimue " CM
until [ "$CM" == 'q' ];do......done具体的就不写了 很简单大家自己改吧!
 
五、写一个脚本,实现引导分区的设定:
1、写一个函数,接受一个参数(参数为目标Linux的boot目录),实现以下功能:
  1)创建一个临时目录/tmp/little.XX;
  2)将宿主机的/boot/initrd-`uname -r`.img文件展开至临时目录;
  3)修改展开而来的init文件:
    a)注释掉如下行:
    echo Scanning and configuring dmraid supported devices
    echo Scanning logical volumes
    lvm vgscan --ignorelockingfailure
    echo Activating logical volumes
    lvm vgchange -ay --ignorelockingfailure  vol0
    resume LABEL=SWAP-sda3
    b)将如下行中的设备修改为你所需要的:
    mkrootdev -t ext3 -o defaults,ro /dev/vol0/root
  4)将修改好的内容重新封闭为cpio的归档文件,并gzip压缩后存放至参数所指定的目录;
  5)复制/boot/vmlinuz-`uname -r`至参数所指定的目录,并重命令为vmlinuz;
2、执行此函数;
3、说明:此处的`uname -r`只是为了引用当前系统正在使用的内核和initrd文件,但这并非是必须。即如果你有其它内核和对应的initrd文件,也可使用。
  1. NBOOT() {
  2. TMPDIR=`mktemp -d /tmp/little.XX`
  3. cd $TMPDIR
  4. zcat /boot/initrd-2.6.18-164.el5.img | cpio -id
  5. sed -i 's/echo Scanning and configuring dmraid supported devices/#&/g' /tmp/$TMPDIR
  6. sed -i 's/echo Scanning logical volumes/#&/g' /tmp/$TMPDIR
  7. sed -i 's/lvm vgscan --ignorelockingfailure/#&/g' /tmp/$TMPDIR
  8. sed -i 's/echo Activating logical volumes/#&/g' /tmp/$TMPDIR
  9. sed -i 's/lvm vgchange -ay --ignorelockingfailure vol0/#&/g' /tmp/$TMPDIR
  10. sed -i 's/resume LABEL=SWAP-sda3/#&/g' /tmp/$TMPDIR
  11. sed -i 's@mkrootdev -t ext3 -o defaults,ro /dev/vol0/root/@mkrootdev -t ext3 -o defaults,ro '"$2"'@#&@g' /tmp/$TMPDIR
  12. find . | cpio -H newc -o --quiet | gzip -9 > $1/initrd.gz
  13. cp /boot/vmlinuz-2.6.18-164.el5 $1/vmlinuz
  14. }
  15. cd
  16. cd younan
  17. source fdisk.sh
  18. NBOOT /mnt/boot ${UDISK}1
 
六、写一个脚本,为目标主机所以磁盘设定grub:
1、写一个函数,接受四个参数(参数1为目标磁盘,参数2为引导分区的挂载点,参数3为内核文件名,参数4为initrd文件名),完成以下功能:
 1)判断挂载点路径的基名是否为boot,如果不是,则停止执行,并提示用户修改;否则,则继续下面的操作;
 2)向目标磁盘安装grub;
 3)在参数3中的子目录grub下建立文件grub.conf;内容类似如下内容:
 default=0
 timeout=10
 title Little Linux
   root (hd0,0)
   kernel /$3
   initrd /$4
2、执行此函数 
  1. GRUB()
  2. {
  3. grub-install --root-directory=$2 $1 &>/dev/null
  4. cd /mnt/boot/grub
  5. touch grub.conf
  6. cat >>grub.conf<
  7. default=0
  8. timeout=10
  9. title Little Linux
  10. root (hd0,0)
  11. kernel /$3 ro root=/dev/sda2
  12. initrd /$4
  13. EOF
  14. }
  15. GRUB /mnt $UDISK vmlinuz initrd.gz
  16. sync
  17. sync
这就是创建一个精简LINUX的步骤和脚本了,有了这个东西你就可以无穷无尽的反复从宿主机里抽取个小LINUX来玩了,是不是十分easy  呢!
刚保存出去看的时候发现似乎有些忘记写#!/bin/bash 啦!匆忙之间的疏漏还请包涵!以上的脚本如果测试有其他错误的话请指出!谢谢!
  1. #!/bin/bash
  2. #
  3. SPART() {
  4. dd if=/dev/zero of=$1 bs=512 count=1
  5. sleep .1
  6. echo "
  7. n
  8. p
  9. 1
  10. +50M
  11. n
  12. p
  13. 2
  14. +521M
  15. n
  16. p
  17. 3
  18. +256M
  19. t
  20. 3
  21. 82
  22. w
  23. " | fdisk $1
  24. mke2fs -j $11
  25. mke2fs -j $12
  26. mkswap -f $13
  27. partprobe $1
  28. }
  29. MYMOUNT (){
  30. if [ -d $2 ] ;then
  31. if mount | awk '{print$3}' | grep "$2" ;then
  32. fuser -km $2
  33. umount $2
  34. mount $1 $2
  35. else
  36. mount $1 $2
  37. fi
  38. else
  39. mkdir $2
  40. mount $1 $2
  41. fi
  42. }
  43. CHROOT() {
  44. if [ -d $1 ] && df -h | grep "$1$"&> /dev/null ;then
  45. cd $1
  46. mkdir -pv boot proc sys dev home root etc/{rc.d,sysconfig,init.d} bin sbin lib usr/{bin,sbin,lib,include} var/{log,run} tmp mnt opt media &> /dev/null
  47. chmod 777 tmp
  48. cd /mnt/sysroot/etc
  49. touch inittab
  50. cat >> inittab <
  51. id:3:initdefault:
  52. si::sysinit:/etc/rc.d/rc.sysinit
  53. #System initialization
  54. l0:0:wait:/etc/rc.d/rc.shutdown
  55. l1:1:wait:/sbin/init -t1 S
  56. EOF
  57. cd
  58. cd /mnt/sysroot/etc/rc.d/
  59. touch /mnt/sysroot/etc/rc.d/rc.sysinit
  60. cat >>/mnt/sysroot/etc/rc.d/rc.sysinit <
  61. #!/bin/bash
  62. echo -e "\t\tWelcome to \033[31mLittle\033[0m Linux..."
  63. mount -n -o remount,rw /
  64. mount -n -a
  65. if [[ -x /sbin/syctl && -r /etc/sysctl.conf ]];then
  66. echo $"configuring kernel parameters..."
  67. /sbi/syctl -p /etc/sysctl.conf
  68. echo $"...kernel parameters done."
  69. fi
  70. /bin/bash
  71. EOF
  72. cd
  73. chmod +x /mnt/sysroot/etc/rc.d/rc.sysinit
  74. cp /etc/sysctl.conf /mnt/sysroot/etc
  75. cd
  76. cd /mnt/sysroot/etc/
  77. touch fastab
  78. cat >> fstab << EOF
  79. /dev/sda2 / ext3 defaults 0 0
  80. /dev/sda1 /boot ext3 defaults 0 0
  81. sysfs /sys sysfs defaults 0 0
  82. proc /proc proc defaults 0 0
  83. EOF
  84. cd
  85. touch /mnt/sysroot/etc/rc.d/rc.shutdown
  86. cat >> /mnt/sysroot/etc/rc.d/rc.shutdown <
  87. #!/bin/bash
  88. #
  89. sync
  90. sleep 2
  91. umount /dev/sda1
  92. umount /dev/sda2
  93. exec /sbin/halt -p
  94. EOF
  95. chmod +x /mnt/sysroot/etc/rc.d/rc.shutdown
  96. else
  97. echo "Warning"
  98. fi
  99. }
  100. MINGLING() {
  101. if which $1;then
  102. DR=`which $1 | grep -o "/.*" | sed -n 's/\(.*\)\/.*/\1/p'`
  103. FR=`which $1 | grep -o "/.*"`
  104. [ -d ${2}$DR ] || mkdir -pv ${2}$DR &> /dev/null
  105. [ -e ${2}$FR ]|| cp $FR ${2}$DR
  106. LIB=`ldd $FR | sed -n 's/.*\/lib\/\(.*\)/\1/gp' | awk '{print $1}'`
  107. for I in $LIB;do
  108. LDR=`ldd $FR | grep -o '/.*' | awk '{print $1}' | sed -n 's@\(/.*\)/'"$I"'@\1@gp'`
  109. [ -d ${2}$LDR ] || mkdir -pv ${2}$LDR &> /dev/null
  110. [ ! -e ${2}"$LDR"/"$LIB" ] && cp -f "$LDR"/"$I" ${2}$LDR
  111. done
  112. else
  113. echo "$1 is not exit."
  114. fi
  115. }
  116. NBOOT() {
  117. TMPDIR=`mktemp -d /tmp/little.XX`
  118. cd $TMPDIR
  119. zcat /boot/initrd-2.6.18-164.el5.img | cpio -id
  120. sed -i 's/echo Scanning and configuring dmraid supported devices/#&/g' $TMPDIR/init
  121. sed -i 's/echo Scanning logical volumes/#&/g' $TMPDIR/init
  122. sed -i 's/lvm vgscan --ignorelockingfailure/#&/g' $TMPDIR/init
  123. sed -i 's/echo Activating logical volumes/#&/g' $TMPDIR/init
  124. sed -i 's/lvm vgchange -ay --ignorelockingfailure vol0/#&/g' $TMPDIR/init
  125. sed -i 's/resume LABEL=SWAP-sda3/#&/g' $TMPDIR/init
  126. sed -i 's@mkrootdev -t ext3 -o defaults,ro /dev/vol0/root/@mkrootdev -t ext3 -o defaults,ro sda2@#&@g' $TMPDIR/init
  127. find . | cpio -H newc -o --quiet | gzip -9 > $1/initrd.gz
  128. cp /boot/vmlinuz-2.6.18-164.el5 $1/vmlinuz
  129. }
  130. GRUB()
  131. {
  132. grub-install --root-directory=/mnt $UDISK &>/dev/null
  133. mkdir /mnt/boot/grub
  134. cd /mnt/boot/grub
  135. touch grub.conf
  136. cat >>grub.conf<
  137. default=0
  138. timeout=10
  139. title Little Linux
  140. root (hd0,0)
  141. kernel /vmlinuz ro root=/dev/sda2
  142. initrd /initrd.gz
  143. EOF
  144. }
  145. read -p "Please choose a disk:" UDISK
  146. fdisk -l $UDISK | grep "^\/dev"
  147. FENQU=`fdisk -l $UDISK | grep "^\/dev" | awk '{print $1}'`
  148. for I in $FENQU;do
  149. if mount | grep "$I" &> /dev/null;then
  150. mount | grep "$I"
  151. else
  152. echo "$I is not mounted"
  153. fi
  154. done
  155. read -p "Next action will destory all date continue(y|N)?:" CHOICE
  156. case $CHOICE in
  157. y|Y)
  158. for I in $FENQU;do
  159. if mount | grep "$I" &> /dev/null;then
  160. mount | grep "$I"
  161. umount $I
  162. fi
  163. done
  164. SPART $UDISK &> /dev/null
  165. ;;
  166. n|N)
  167. exit
  168. ;;
  169. *)
  170. exit
  171. ;;
  172. esac
  173. sleep 2
  174. MYMOUNT ${UDISK}1 /mnt/boot
  175. MYMOUNT ${UDISK}2 /mnt/sysroot
  176. CHROOT /mnt/sysroot
  177. for CM in ls cp sysctl mingetty swapon halt poweroff chown chmod which who swapoff shutdown runlevel reboot mount umount init bash clear vi sync sleep ping lsmod insmod modprobe touch mkdir hostname mv rm vi vim cat ifconfig;do
  178. MINGLING $CM /mnt/sysroot
  179. done
  180. ln -sv bash sh &> /dev/null
  181. NBOOT /mnt/boot ${UDISK}1
  182. GRUB
  183. sync
  184. sync
  185. sleep 2
 
阅读(1160) | 评论(0) | 转发(0) |
0

上一篇:LINUX学习之路11

下一篇:LINUX学习之路13

给主人留下些什么吧!~~