打造自己的專屬Linux(二):使用指令碼實現自動化建立小Linux與命令移植

來源:互聯網
上載者:User

這是我前幾天在馬哥的帶領下寫的6個指令碼,他們串起來就可以實現(一)篇一所有的功能,很方便吧我們以後要通過不斷倒騰這個小linux,來由淺入深的學習linux的系統構架和調優,最後實現編譯核心,真正意義上打造自己的Linux,如果你有興趣,那我一起學習吧強烈建議自己動手寫出這六個指令碼,對指令碼的學習協助非常大。

這六個指令碼其實就是(一)篇的幾個步驟組合起來,它們連在一起就可以完全實現(一)篇的目的,六個指令碼如下:

一、寫一個指令碼,實現將一個硬碟中原有分區資訊全部刪除,並重新將其分為三個區:
1、提示使用者指定要操作的磁碟;如果此硬碟中有新區,顯示分區資訊,並判斷此中分區是否仍然處於掛載狀態;
   如果是,則顯示分區和對應的掛載點;否則,則說明分區沒有掛載;
2、提示使用者接下來操作會破壞硬碟上的所有資料,並詢問使用者是否繼續進行;形如:Continue(y/N)?
   如果使用者選擇繼續,則抹除此硬碟上的所有分區資訊(如果是仍處理掛載狀態的分區,則需要先卸載);否則退出;
3、將此硬碟分為三個主要磁碟分割:
第一個主要磁碟分割,50M,ext3檔案系統
第二個主要磁碟分割,512M,ext3檔案系統
第三個主要磁碟分割,256M,swap檔案系統
要求:上面第2和第3步要求用函數實現;函數執行結束要有傳回值;

#!/bin/bash#the script:rmdisk3.shfunction CH {                                                                             #題目要求的第二個功能 read -p "WARMING!The next action will clean the DISK!COTINUE?(Y|y.other for quite)" CH if [ $CH == 'Y' -o $CH == 'y' ];then    MOUNT=`mount | grep $1`                                                  #通過grep來抓取mount裡的指定磁碟,看是否被掛載    for i in $MOUNT;do                                                       #用for迴圈列表來一個一個卸載掉掛載的分區       i=`mount | grep /dev/sdb | awk '{print $1}'`       fuser -km $i                                                          #這個命令用於剔除分區裡的活動使用者保證卸載       umount $i       return 0    done  else    exit  fi}function FDISK {                                                 #格式化所選磁碟為3個分區  dd if=/dev/zero of=$1 bs=512 count=1                           #dd命令比較特殊它是一種特殊的複製   /dev/zero是一個特殊裝置用於吐出0,它們組合起來  partprobe $1                                                   #意思就是給指定磁碟的第0個塊輸出512個位元組0,等於破壞掉他的bootloader和分區資訊echo '                                                           #使用partprobe命令重讀下分區,確保格式化順利進行                                  np1+50Mnp2+512Mnp3+256Mt382w' | fdisk $1 &> /dev/null  partprobe $1  sleep 1                                                         #這裡要睡1秒,等待系統將分區資訊讀入  mke2fs -j ${1}1 &> /dev/null                                    #格式化三個分區  mke2fs -j ${1}2 &> /dev/null  mkswap ${1}3 &> /dev/null}read -p "Chose a disk:" DISK                                      #下面的是提醒使用者的資訊  fdisk -l $DISK | grep ^/devfor I in `fdisk -l $DISK | grep ^/dev |awk '{print $1}'`;do  mount | grep "$I"    if [ $? -ne 0 ];then      echo "The $I is not mounted."    else      echo "The $I is mounted"    fidoneread -p "Countinue?(y|n)" P  if [ $P == 'Y' -o $P == 'y' ];then       CH $DISK       FDISK $DISK       echo -e "\033[32mThe action is suceess!\033[0m"      else       exit  fi

二、寫一個指令碼,實現將上述步驟中建立的分區掛載至某目錄:
1、寫一個函數,接受兩個參數,完成以下功能:   
   參數1為/boot分區對應的裝置,傳遞至函數之後將其掛載至/mnt/boot;
   參數2為/分區對應的裝置,傳遞至函數之後將其掛載至/mnt/sysroot;
   說明:上述的掛載點/mnt/boot和/mnt/sysroot如果事先不存在,需要先建立;如果事先存在,
   且已經被某裝置掛載使用,則需要先卸載原來掛載的裝置;
2、將第一個指令碼中實現的分區1和分區2傳遞給些函數執行;

#!/bin/bash# source /root/LX/1               #這條命令用於串連第一個指令碼,可以引用它的變數,路徑一定要對,/root/LX/1是我的存放路徑#目錄/mnt/boot是否存在,如果不存在,建立,並掛載上磁碟。如果存在,踢掉裡面的活動人員,卸載掛載的磁碟,掛載上剛格式化的分區1function MOUNT {      [ -d $A ] &> /dev/null || mkdir $A && fuser $A | umount $A &> /dev/null | mount ${DISK}1 $A      sleep 1      [ -d $B ] &> /dev/null || mkdir $B && fuser $B | umount $B &> /dev/null | mount ${DISK}2 $B}A=/mnt/bootB=/mnt/sysrootMOUNT $A $B

三、寫一個指令碼,初始化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
   而後給此檔案以執行許可權;
   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、執行此函數

#!/bin/bash#source /root/LX/2function ROOTFS {[ -d $B ] && ( mount | grep "$B" &> /dev/null ) || echo "ERRO!The $B is not mounted" | read -p "Countinue?(y|n)" INPUT  if [ "$INPUT" == 'n' ];then                                       #這是一個判斷函數,防止意外情況發生      exit  fi  cd $B                                              #建立目錄  mkdir -p 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  chmod 1777 tmpcat >> etc/inittab << EOF                             #建立題目要求的幾個檔案id:3:initdefault:si::sysinit:/etc/rc.d/rc.sysinitEOFcat >> etc/rc.d/rc.sysinit << EOF#!/bin/bashecho -e "\t\tWelcome to \033[31m;1mLittle\033[0m Linux..."mount -n -o remount,rw /mount -n -a/bin/bash EOF  chmod 755 etc/rc.d/rc.sysinitcat >> etc/fstab << EOF/dev/sda2               /                       ext3    defaults        0 0/dev/sda1               /boot                   ext3    defaults        0 0sysfs                   /sys                    sysfs   defaults        0 0proc                    /proc                   proc    defaults        0 0EOF}ROOTFS $B

四、寫一個指令碼,實現二進位命令及對應庫檔案的拷貝:
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、執行此函數;

#!/bin/bash#function LDD {  which $1 &> /dev/null || echo "It is not exist" | retrun 5                  #這裡也是一個判斷  DIR=`which $1 | grep -o "/.*"`                   #防止有別名的命令導致截取錯誤的路徑         DIR1=`echo $DIR | sed "s@\(.*\)$1@\1@g"`  [ -d $B$DIR1 ] || mkdir $B$DIR1               #如果要複製的目錄不存在,建立它  [ -e $B$DIR ] || cp $DIR $B$DIR1              #如果檔案不存在才複製它  for I in `ldd $DIR | grep -o "/[^[:space:]]*"`;do        #這裡使用ldd命令指定命令的執行檔案存放路徑,並通過for迴圈來複製它的庫檔案      DIR1=`echo $I | sed "s@\(.*\)/[^/]*@\1@g"`      [ -d $B$DIR1 ] || mkdir $B$DIR1                #這裡的判斷同上      [ -e $B$I ] ||cp $I $B$DIR1 << EndnEnd  done}  B=/mnt/sysroot  read -p "Which command you want add:" COM  LDD $COM

五、寫一個指令碼,實現引導分區的設定: 
1、寫一個函數,接受一個參數(參數為目標Linux的boot目錄),實現以下功能:
  1)建立一個臨時目錄/tmp/litte.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檔案,也可使用。

#!/bin/bash#source /root/LX/3KERNEL=vmlinuzINITRD=initrd.gzfunction BOOT {                                                                    #這個函數解開initrd檔案,並寫入資訊後重新歸檔封裝     DIR=`mktemp -d /tmp/litte.XX`                              #建立臨時目錄     cd $DIR     zcat /boot/initrd-`uname -r`.img | cpio -id                  #釋放initrd到一個臨時目錄     sed -i 's@echo Scanning and configuring dmraid supported devices@#&@g' init           #修改     sed -i 's@echo Scanning logical volumes@#&@g' init     sed -i 's@lvm vgscan --ignorelockingfailure@#&@g' init     sed -i 's@echo Activating logical volumes@#&@g' init     sed -i 's@lvm vgchange -ay --ignorelockingfailure  vol0@#&@g' init     sed -i 's@resume LABEL=SWAP-sda3@#&@g' init     sed -i "s@\(mkrootdev.* \).*@\1${DISK}2@g" init     find . | cpio -H newc -o --quiet | gzip -9 > $1/initrd.gz                #再次歸檔壓縮     CP /Boot/vmlinuz-`uname -r` $1/vmlinuz                       #複製修改並歸檔後的initrd檔案到我們的小linux /boot裡     rm -rf $DIR                      #要養成刪臨時檔案的好習慣}BOOT $A

六、寫一個指令碼,為目標主機所以磁碟設定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、執行此函數

#!/bin/bash#source /root/LX/5function GRUB {[ `basename $2` != boot ] && echo "The mounted dir is wrong!Modiy it!" && exit            #判斷,防止出錯grub-install --root-directory=/mnt/ $1 &> /dev/null                      #安裝grubcat >> $2/grub/grub.conf << EOF                                          #建立grub.conf檔案default=0timeout=10title Little Linux        root (hd0,0)         kernel /$3   ro root=${DISK}2 quite        initrd /$4EOF}GRUB $DISK $A $KERNEL $INITRD

好了,就是這6個指令碼~寫出來後對自己的協助非常大!


下篇預告:打造自己的專屬Linux(三):給小linux添加網路模組,實現關機重啟,登入介面











相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.