修改initrd做miniLinux

开始试着修改initrd做miniLinux,需要向其中添加命令,慢慢完善。但是用ldd命令查看哪些大串的库再拷贝实在是纠结~

自动实现一下:

描述:

  输入命令后,自动寻找命令位置,将命令拷到对应根位置后,并且查询到所需的库文件,逐一的拷贝到定义好的位置。

    第二次修改给脚本添加了了参数,实现了可以在脚本中调用,并且直接传 递命令选项给脚本的功能;但是用户使用的时候可以指定以交互式方式进行;
  缺陷:能够实现的拷贝有局限,由于对/lib、/usr/lib、 /usr/local/lib几个位置区分比较麻烦,
现在脚本还进能实现拷贝/lib下的库到对应威之下的功能;有时间了会不断改进;
 
 
  1. #!/bin/bash
  2. #Author: Mo
  3. #Descripution: auto copy libs to specify site.
  4. #Date & Time: 2011-03-10-20:04:31
    #Version : 1.2.1
    #

    sysroot=/mnt/sysroot
    file=`mktemp /tmp/lddtmp.XXXX`

    mytrap() {
    rm -rf ${file}
    echo -e "\nQuit........\n "
    exit 1
    }
    trap "mytrap" SIGINT

  5. #read -p "Input your command: " comm
    while getopts ':s:u' SWITCH;do
    case $SWITCH in
    s) comm=$OPTARG
    echo "$OPTARG"
    ;;
    u) read -p "Input your command: " comm
    ;;
    \?) echo -e "Unknown option...\nUSAG: ./autolib.sh [-u]|[-s command]."
    exit 1
    ;;
    esac
    done

    if ! which $comm &>/dev/null ;then
    echo -e "\033[31mNo command:\033[0m ${comm}"
    exit 1
    else
    cpath=`which --skip-alias ${comm}`
    ldd ${cpath} | grep ".*[[:space:]]/.*[[:space:]]" | sed "s@.*[[:space:]]\(/.*[[:space:]]\)(.*)@\1@g" > ${file}

    #cp command
    cp -u ${cpath} ${sysroot}${cpath}
    sync

    #cp libs
    #NOTICE: this shell below can onlp copy libs from directory /lib , ro it may case problem;
    while read LINE ;do
    if [ -h $LINE ];then
    orglib=`ls -l $LINE | awk '{printf $11}'`
    /bin/cp -d $LINE "${sysroot}/lib"
    /bin/cp -d /lib/${orglib} "${sysroot}/lib"
    sync
    else
    /bin/cp -d $LINE "${sysroot}/lib"
    fi
    done < ${file}
    sync;sync

    echo -e "Path: " ${cpath} "\nAll have synced."
    fi

    #do some cleaning...
    rm -f ${file}

    wait
    echo "Copy has done."
  6. 创建一个MiniLinux:

      通过对RamDisk(Initrd)分析,现在了解了initrd的主要原理及工作流程,为了加深对该过程的理解,下面使用initrd创建一个微型的linux系统,也更加深对linux开机过程的原理性了解:并用脚本实现该过程;

     环境:宿主机:RedHat 5.4 内核:2.6.18

     要求:首先实现最基本的启动,正常启动后给用户一个shell;后期拓展,需要实现将根文件系统挂载为RW,实现命令:mount、umount、vi、ls、touch、mkdir等。也可以后期按照需求添加各项功能,逐渐丰富;

    1. 配置所需的环境:新增硬盘/dev/sdb(大小512M~1G绰余)、建立所需目录(这里假定新增的硬盘为sdb)

        
        
    1. # mkdir  -v  /mnt/sysroot  
    2. # mkdir  -v  /mnt/boot 
    3. # mkdir  -v  /tmp/init 
    4.  

      注:在虚拟机里面添加硬盘时将硬盘放到自己容易找到的位置,最好不用默认位置;

    2. 对新硬盘分区,格式化后挂载到/mnt目录下的适当位置

        
        
    1. # fdisk  /dev/sdb   (将硬盘分为两个区,第一个100M作为boot分区,第二个作为根分区) 
    2. # partproble  /dev/sdb   
    3. # mkfs -t ext3 /dev/sdb1 
    4. # mkfs -t ext3 /dev/sdb2  
    5. # mount /dev/sdb1 /mnt/boot 
    6. # mount /dev/sdb2 /mnt/sysroot 
    7. # mount  (查看挂载是否成功) 
    8.  

    3. 拷贝内核文件到相应的位置,并且解包initrd

        
        
    1. # cp /boot/vmlinuz-`uname -r`.img /mnt/boot/vmlinuz 
    2. # cd /tmp/init 
    3. # zcat /boot/initrd.2.6.18-164.el5.img | cpio -id  &> /dev/null 
    4.  

    4. 修改RamDisk内容:

        
        
    1. # sed -i s/\(mkrootdev.*ro[[:space:]]\).*/\1sda2/g /tmp/init 
    2.  

      上步骤中将RanDisk解压出来init文件中的”mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00”项修改为”mkrootdev -t ext3 -o defaults,ro sda2”;并且可以根据实际需求,将该文件中不需要加载的dm-mirror、dm-zero、dm-snapshrot项注释或删掉;当然为了更加精简镜像文件的大小,可以到对应的/lib文件夹下删除相应的文件;

    initrd文件修改后示例:

        
        
    1. #!/bin/nash 
    2. mount -t proc /proc /proc 
    3. setquiet 
    4. echo Mounting proc filesystem 
    5. echo Mounting sysfs filesystem 
    6. mount -t sysfs /sys /sys 
    7. echo Creating /dev 
    8. mount -o mode=0755 -t tmpfs /dev /dev 
    9. mkdir /dev/pts 
    10. mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts 
    11. mkdir /dev/shm 
    12. mkdir /dev/mapper 
    13. echo Creating initial device nodes 
    14. mknod /dev/null c 1 3 
    15. mknod /dev/zero c 1 5 
    16. mknod /dev/systty c 4 0 
    17. mknod /dev/tty c 5 0 
    18. mknod /dev/console c 5 1 
    19. mknod /dev/ptmx c 5 2 
    20. mknod /dev/rtc c 10 135 
    21. mknod /dev/tty0 c 4 0 
    22. mknod /dev/tty1 c 4 1 
    23. mknod /dev/tty2 c 4 2 
    24. mknod /dev/tty3 c 4 3 
    25. mknod /dev/tty4 c 4 4 
    26. mknod /dev/tty5 c 4 5 
    27. mknod /dev/tty6 c 4 6 
    28. mknod /dev/tty7 c 4 7 
    29. mknod /dev/tty8 c 4 8 
    30. mknod /dev/tty9 c 4 9 
    31. mknod /dev/tty10 c 4 10 
    32. mknod /dev/tty11 c 4 11 
    33. mknod /dev/tty12 c 4 12 
    34. mknod /dev/ttyS0 c 4 64 
    35. mknod /dev/ttyS1 c 4 65 
    36. mknod /dev/ttyS2 c 4 66 
    37. mknod /dev/ttyS3 c 4 67 
    38. echo Setting up hotplug. 
    39. hotplug 
    40. echo Creating block device nodes. 
    41. mkblkdevs 
    42. echo "Loading uhci-hcd.ko module" 
    43. insmod /lib/uhci-hcd.ko  
    44. echo "Loading ohci-hcd.ko module" 
    45. insmod /lib/ohci-hcd.ko  
    46. echo "Loading ehci-hcd.ko module" 
    47. insmod /lib/ehci-hcd.ko  
    48. mount -t usbfs /proc/bus/usb /proc/bus/usb 
    49. echo "Loading jbd.ko module" 
    50. insmod /lib/jbd.ko  
    51. echo "Loading ext3.ko module" 
    52. insmod /lib/ext3.ko  
    53. echo "Loading scsi_mod.ko module" 
    54. insmod /lib/scsi_mod.ko  
    55. echo "Loading sd_mod.ko module" 
    56. insmod /lib/sd_mod.ko  
    57. echo "Loading scsi_transport_spi.ko module" 
    58. insmod /lib/scsi_transport_spi.ko  
    59. echo "Loading mptbase.ko module" 
    60. insmod /lib/mptbase.ko  
    61. echo "Loading mptscsih.ko module" 
    62. insmod /lib/mptscsih.ko  
    63. echo "Loading mptspi.ko module" 
    64. insmod /lib/mptspi.ko  
    65. echo "Loading dm-mod.ko module" 
    66. insmod /lib/dm-mod.ko  
    67. echo Waiting for driver initialization. 
    68. stabilized --hash --interval 250 /proc/scsi/scsi 
    69. echo Making device-mapper control node 
    70. mkdmnod 
    71. mkblkdevs 
    72. echo Creating root device. 
    73. mkrootdev -t ext3 -o defaults,ro /dev/sda2  (这里请按照自己使用的情况进行修改,我的下一步实验环境为单盘,但是如实验者的环境非但盘,请依照次序进行调整)
    74. echo Mounting root filesystem. 
    75. mount /sysroot 
    76. echo Setting up other filesystems. 
    77. setuproot 
    78. echo Switching to new root and running init. 
    79. switchroot 
    80.  

    5. 重新打包修改好的镜像到相应位置:

        
        
    1. # find . | cpio --quiet -H newc -o |gzip -9 -n > /mnt/boot/initrd.gz 
    2. # cd /mnt/boot/ ; ls    (查看生成镜像)
    3.  

      命令解释:找本目录下修改好的的全部文件,用管道送给cpio进行打包,使用静默模式,-H制定创建的归档文件类型为newc(是一种支持的文件个数的inode号大于65535的文件模型),并且用 -o 进行输出,输出的流用gzip压缩,使用最大压缩比9,创建出的压缩文件输出至/mnt/boot路径下

    6. 安装grub到新加的硬盘上:

        
        
    1. # grub-install --root-directory=/mnt  /dev/sdb 
    2.  注: --root-directory指定安装的位置,并且命令会自己寻找目录下的boot目录来进行安装;

    7. 编辑生成grub配置文件
       安装后缺少grub.conf文件,需要手动建立,也可以将宿主机上的文件拷贝后进行相应的修改:
        格式如下:

        
        
    1. timeout=5 
    2. default=0 
    3.  
    4. title MyLinux 
    5.     root (hd0,0) 
    6.     kernel /vmlinuz ro root=/dev/sda2 
    7.     initrd /initrd.gz 
    8.  

    8. 在根分区sysroot目录下创建基本目录:

        
        
    1. # cd /mnt/sysroot 
    2. # mkdir -pv bin dev etc lib sbin sys tmp proc tmp 
    3. # chmod 1777 ./tmp  
    4.  

    9.  拷贝基本的/sbin/init及/bin/bash文件到相应的位置(这两个是最基本的,也可附加其他的命令,自己扩展):

        
        
    1. # cp /bin/bash  /mnt/sysroot/bin 
    2. # cp /sbin/init  /mnt/sysroot/sbin 
    3.  

    10. 拷贝相应命令的lib库文件:
      (注意某些库文件是链接文件,需要将链接及源文件一块拷过去。)

        
        
    1. # ldd /bin/bash
    2.  
    3. # ldd /sbin/init
    4.  
    5. # cp -d /lib/libsepol.so.1 /mnt/sysroot/lib/ 
    6.  

    如下ldd命令显示的信息:其中有库文件的全路径;根据路径拷贝库文件:

     注:linux-gate.so.1 是一个虚拟的库标志,所以不需要拷贝;

       cp命令的 -d 参数可以拷贝指定的原文件(区别源文件),若拷贝的是一个链接,则拷贝的是该链接文件;若拷贝链接文件时不加-d参数会使拷贝的时库链接的源文件,这样可能造成某些共享性库的错误;

     拷贝后,查看,发现有源文件需要拷贝,再拷贝链接文件指向的源文件:


     
      在库完全链接正确后不会再有颜色显示警告;
      上面只是拷贝一部分库的实例,在拷贝时需要对照拷贝进去所有的库文件;

    11. 建立init的配置文件/etc/inittab (bash脚本文件注意给予相应的权限)

        
        
    1. #  vim /mnt/sysroot/etc/inittab 
    2.  文件编辑格式如下: 
    3.  
    4. id:3:initdefault:  (设置系统默认运行级别)
    5. si::sysinit:/etc/rc.d/rc.sysinit  (置系统初始化脚本位置)
    6.  


    12. 建立系统调用系统初始化时需要的/etc/rc.d/rc.sysinit脚本:

        
        
    1. # vim  /mnt/sysroot/etc/rc.d/rc.sysinit 
    2.   编辑文件格式如下: 
    3. #!/bin/bash
    4. echo -e “\tWelcome to \033[31mMyLinux\033[0m.” 
    5. /bin/bash 
    6.  

      :设置进入系统初始化界面需要的东西。可以不输出信息,但是需要运行bash,进入bash环境

      注:在实际系统中init读取inittab文件,按照文件中的配置依次进行下面工作:

           inittdefault   定义系统默认运行级别;

           rc.sysint    初始化系统的网络,文件系统等

           /etc/rc.d/rc N  执行相应的运行相应级别下的服务脚本

           mingetty    提供用户登陆认证,在认证成功后自动调用/bin/bash,为用户提供接口

           /etc/X11/prefdm -nodeamon 如果有设置,开启X界面

      但是在该小型linux中,没有登录认证功能,所以需要在系统初始化完成后显式的为用户提供shell。

     

    13. 关闭宿主机系统;新建一个虚拟机,硬盘选为刚才创建的硬盘,开机测试;

     

     

     

    用shell脚本实现上述创建过程:

      系统环境跟上述描述一致,需要先新建硬盘,并且过程中使用了我文章《脚本,自动查找并拷贝库》中的脚本来自动拷贝库,需要将调用的脚本路径添加到PATH路径下,否则会造成出错;

        
        
    1. #!/bin/bash 
    2. #Author: Mo 
    3. #Date & Time: 2011-03-10 20:19:20 
    4. #Description: auto create a minilinux  
    5. #Version : 1.2.1 
    6.  
    7. tmpdir=`mktemp -d /tmp/init.XXXX` 
    8. disk=/dev/sdb 
    9. sysroot=/mnt/sysroot 
    10. sysboot=/mnt/boot 
    11.  
    12. # Partition the disk 
    13. echo "n 
    14. 13 
    15. 14 
    16. +1000M 
    17. W" | fdisk ${disk} &>/dev/null 
    18. wait 
    19.  
    20. #update /proc/partitions 
    21. /sbin/partprobe ${disk} 
    22. sleep 5 
    23. # making file system 
    24. /sbin/mkfs -t ext3 ${disk}1 
    25. wait 
    26. /sbin/mkfs -t ext3 ${disk}2 
    27. wait 
    28.  
    29. mkdir -pv ${sysboot} ${sysroot} 
    30.  
    31. #update /proc/partitions 
    32. /sbin/partprobe &> /dev/null 
    33. sleep 5 
    34. #mount disk 
    35. /bin/mount -t ext3 ${disk}1  ${sysboot} 
    36. /bin/mount -t ext3 ${disk}2  ${sysroot} 
    37. wait 
    38.  
    39. #kernel; 
    40. cp /boot/vmlinuz-`uname -r` /mnt/boot/vmlinuz 
    41. sync 
    42.  
    43. #create initrd; 
    44. cd ${tmpdir} 
    45. /bin/zcat /boot/initrd-*.img | cpio -id  &>/dev/null 
    46. sed -i  s@mkrootdev.*@'mkrootdev -t ext3 -o defaults,ro /dev/sda2'@  ./init 
    47. sync 
    48. find . | cpio --quiet -H newc -o | gzip -9 -n >/mnt/boot/initrd.gz 
    49. wait 
    50.  
    51. #grub 
    52. grub-install --root-directory=/mnt ${disk} &>/dev/null 
    53. touch ${sysboot}/grub.conf 
    54. echo "default=0 
    55. timeout=2 
    56. title  MyLinux 
    57. root (hd0,0) 
    58. kernel  /vmlinuz 
    59. initrd  /initrd.gz" > /mnt/boot/grub/grub.conf 
    60. sync 
    61.  
    62. #create basic directorys in sysroot 
    63. mkdir  -p $sysroot/{etc/rc.d,dev,lib,bin,sbin,proc,sys,tmp}  &>/dev/null 
    64. chmod 1777 ${sysroot}/tmp 
    65. wait 
    66.  
    67. #cp libs 
    68. #bash ls mount bash vi 
    69. autolib.sh  -s init
    70. sleep 1 
    71. /root/bin/autolib.sh -s bash
    72. sleep 1
    73. autolib.sh  -s ls 
    74. sleep 1 
    75. #/tmp/autolib.sh  -s vim 
    76. autolib.sh  -s mount 
    77. sleep 1 
    78. autolib.sh  -s umount 
    79. sleep 1 
    80. chmod a+x ${sysroot}/{bin,sbin}/* 
    81. wait 
    82.  
    83. #create file /etc/inittab 
    84. echo "id:3:initdefault: 
    85. si::sysinit:/etc/rc.d/rc.sysinit" >${sysroot}/etc/inittab 
    86.  
    87. #create file  /etc/rc.d/rc.sysinit 
    88. echo '#!/bin/bash
    89. mount -n -o remount,rw /dev/sda2 /  
    90. echo -e "\tWelcome to \033[31mMy Linux\033[0m" 
    91. /bin/bash' > ${sysroot}/etc/rc.d/rc.sysinit 
    92. chmod a+x ${sysroot}/etc/rc.d/rc.sysinit 
    93.  
    94. echo "All Done....... 
    95. Then you can test the miniLinix." 

     

    拓展参考:

    http://www.ibm.com/developerworks/cn/linux/l-initrd.html(IBM上面用busybox实现了一个精简的initrd)

     整理过程,难免出错,希望共同探讨;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值