這是我前幾天在馬哥的帶領下寫的6個腳本,他們串起來就可以實現(一)篇一所有的功能,很方便吧我們以後要通過不斷倒騰這個小linux,來由淺入深的學習linux的系統構架和調優,最後實現編譯內核,真正意義上打造自己的Linux,如果你有興趣,那我一起學習吧強烈建議自己動手寫出這六個腳本,對腳本的學習幫助非常大。
這六個腳本其實就是(一)篇的幾個步驟組合起來,它們連在一起就可以完全實現(一)篇的目的,六個腳本如下:
一、寫一個腳本,實現將一個硬盤中原有分區信息全部刪除,並重新將其分爲三個區:
1、提示用戶指定要操作的磁盤;如果此硬盤中有新區,顯示分區信息,並判斷此中分區是否仍然處於掛載狀態;
如果是,則顯示分區和對應的掛載點;否則,則說明分區沒有掛載;
2、提示用戶接下來操作會破壞硬盤上的所有數據,並詢問用戶是否繼續進行;形如:Continue(y/N)?
如果用戶選擇繼續,則抹除此硬盤上的所有分區信息(如果是仍處理掛載狀態的分區,則需要先卸載);否則退出;
3、將此硬盤分爲三個主分區:
第一個主分區,50M,ext3文件系統
第二個主分區,512M,ext3文件系統
第三個主分區,256M,swap文件系統
要求:上面第2和第3步要求用函數實現;函數執行結束要有返回值;
#!/bin/bash
#the script:rmdisk3.sh
function 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命令重讀下分區,確保格式化順利進行
n
p
1
+50M
n
p
2
+512M
n
p
3
+256M
t
3
82
w' | 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 ^/dev
for 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"
fi
done
read -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是否存在,如果不存在,創建,並掛載上磁盤。如果存在,踢掉裏面的活動人員,卸載掛載的磁盤,掛載上剛格式化的分區1
function 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/boot
B=/mnt/sysroot
MOUNT $A $B
三、寫一個腳本,初始化rootfs1、寫一個函數,接受一個參數(參數爲第二步驟中掛載的/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/2
function 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 tmp
cat >> etc/inittab << EOF #創建題目要求的幾個文件
id:3:initdefault:
si::sysinit:/etc/rc.d/rc.sysinit
EOF
cat >> etc/rc.d/rc.sysinit << EOF
#!/bin/bash
echo -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.sysinit
cat >> etc/fstab << EOF
/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
EOF
}
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 << End
n
End
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/3
KERNEL=vmlinuz
INITRD=initrd.gz
function 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/5
function GRUB {
[ `basename $2` != boot ] && echo "The mounted dir is wrong!Modiy it!" && exit #判斷,防止出錯
grub-install --root-directory=/mnt/ $1 &> /dev/null #安裝grub
cat >> $2/grub/grub.conf << EOF #創建grub.conf文件
default=0
timeout=10
title Little Linux
root (hd0,0)
kernel /$3 ro root=${DISK}2 quite
initrd /$4
EOF
}
GRUB $DISK $A $KERNEL $INITRD
好了,就是這6個腳本~寫出來後對自己的幫助非常大!
下篇預告:打造自己的專屬Linux(三):給小linux添加網絡模塊,實現關機重啓,登錄界面