红联Linux门户
Linux帮助

用Shell脚本实现自动化完成属于自己的微型Linux

发布时间:2014-12-17 15:06:24来源:linux网站作者:wei2856059

前面我写了如何通过宿主RedHat系统通过精简和调用以及修改的方式,打造一个完全属于自己的微型LInux!

但是,很多人懒啊~~,所以我又写了写脚本,通过分步实现的方式。达到用一个脚本,完全的按照用户想要达到的目的安装一个属于自己的微型Linux。

那么下面我们来看如何实现:

实现过程分析:

1.分区,按照用户所选的盘,将其格式化,分区

2.挂载,按照用户设定的的分区好的盘分别挂载在我们宿主机的一个目录上。方便对微型linux进行编辑。

3.对微型Linux进行写入各项配置信息

4.将微型Linux中我们需要用到的Bash等命令放进去

5.放入内核,和启动必须加载的配置文件

6.对用户的硬盘安装引导程序。

好的~过程已经分析OK了,下面我们动手开始写吧!!!

第一步:实现自动分区!!

我们将问题分开来看,于是成了这样:

写一个脚本,实现将一个硬盘中原有分区信息全部删除,并重新将其分为三个区:
1、提示用户指定要操作的磁盘;如果此硬盘中有分区,显示分区信息,并判断此中分区是否仍然处于挂载状态;
   如果是,则显示分区和对应的挂载点;否则,则说明分区没有挂载;
2、提示用户接下来操作会破坏硬盘上的所有数据,并询问用户是否继续进行;形如:Continue(y/N)?
   如果用户选择继续,则抹除此硬盘上的所有分区信息(如果是仍处理挂载状态的分区,则需要先卸载);否则退出;
3、将此硬盘分为三个主分区:
  第一个主分区,50M,ext3文件系统
  第二个主分区,512M,ext3文件系统
  第三个主分区,256M,swap文件系统

OK,开始实现:

#!/bin/bash  
#: Title: All_Mini_Linux.sh  
#: Synopsis:  
#: DateTime: 2011-08-04 00:36:35  
#: Version: 0.1  
#: Author: weiyan  
#: Options:
#  
read -p "The target disk: " DSK# 提示用户选择即将分区的硬盘 
 
if fdisk -l $DSK | grep "^/dev" &> /dev/null ; then #判断硬盘的分区状态。 
  fdisk -l $DSK | grep "^/dev" 
  PARTS=`fdisk -l $DSK | grep "^/dev" | awk '{print $1}'` 
 
  for I in $PARTS; do  # 使用循环的方式,将硬盘上每一个分区的状态和是否挂载,挂载在哪告诉用户。 
if mount | grep "$I" &> /dev/null; then 
   mount | grep "$I" 
else 
  echo "$I is not mounted." 
fi 
  done 
fi 
 
SPART() {# 制作名为SPART的函数,这个函数的功能就是提示用户准备分区,当允许分区则开始分区! 
  read -p "Warning !!!!! Next you do it will wipe your disk !!!! Continue(y/N)?" CHOICE 
  case $CHOICE in 
  y|Y) 
  for I in $PARTS; do 
if mount | grep "$I" &> /dev/null; then 
  fuser -km $I 
  umount $I 
fi 
  done 
 
  dd if=/dev/zero of=$DSK bs=512 count=1 &> /dev/null   # 将用户所选的硬盘的MBR直接擦除。让其成为空盘。 
 
echo '  
n
p

 
+50M 



 
+512M 



 
+256M 


82 
w' | fdisk $DSK &> /dev/null  # 将分区的信息传递给 fdisk,开始分区。 
 
  partprobe $DSK 
  sleep 1   # 分区之后要用sleep命令让系统“沉睡”1秒,这样可以让分区的信息真正的同步进硬盘,而不至于格式化出错。 
 
  mke2fs -j ${DSK}1 &> /dev/null# 分别格式化每一个分区并且格式化虚拟分区。 
  mke2fs -j ${DSK}2 &> /dev/null 
  mkswap ${DSK}3 &> /dev/null 
  return 0 
  ;; 
  n|N) 
return 1 
;; 
  *) 
return 2 
;; 
esac 

SPART  # 执行这个 SPART 函数。 
[ $? -eq 0 ] && echo "The Disk wipe success !!!!!!!" || echo "Failure"# 判断函数的返回值,如果是0,则提示分区成功。 

这样一来,我们就有了一个完整的分好了区,并且格式化了的硬盘了。接下来呢?

将硬盘挂载!

第二步:挂载!

那么将第二步好好的整理一下,发现它其实是不是实现了下面的功能呢?

写一个脚本,实现将上述步骤中创建的分区挂载至某目录:
1、写一个函数,接受两个参数,完成以下功能: 
   参数1为/boot分区对应的设备,传递至函数之后将其挂载至/mnt/boot;
   参数2为/分区对应的设备,传递至函数之后将其挂载至/mnt/sysroot;
   说明:上述的挂载点/mnt/boot和/mnt/sysroot如果事先不存在,需要先创建;如果事先存在,且已经被某设备挂载使用,则需要先卸载原来挂载的设备;
2、将第一个脚本中实现的分区1和分区2传递给些函数执行;

那么,目标有了,我们来实现它!

function GUAZAI {  # 创建一个名为 GUAZAI 的函数 
[ -d /mnt/boot ] ||  mkdir -p /mnt/boot# 先判断我们要挂载的目录在不在,如果不在,则创建。 
umount /mnt/boot &> /dev/null  # 当有了目录之后,直接先卸载掉它,不管他之前有没有被挂载。(让我懒一下把-。-) 
mount $1 /mnt/boot # 挂载我们指定的参数1的目录,到挂载点。 
[ -d /mnt/sysroot ] || mkdir -p /mnt/boot   # 同上,判断第二个。 
umount /mnt/sysroot &> /dev/null 
mount $2 /mnt/sysroot 

 
GUAZAI ${DSK}1 ${DSK}2 #  执行这个函数,并传递给它两个需要挂载的分区参数。 

OK,挂载也挂载完了,接下来呢?

第三步:写入配置信息!

分析一下,我们要写入的配置信息:

首先要在我们的第二块分区上创建各种各样的文件夹,比如/bin /sbin /usr /root /home /tmp /etc 等等等等。

然后我们要创建/etc/inittab 这个文件

之后创建读取分区信息挂载信息的文件/etc/fstab

再然后呢?创建/etc/rc.d/rc.sysinit文件~

ok~分析得当!开始着手写入吧!

#这里我们使用函数,传递参数,参数只有$1,而$1则是我们的分区2所挂载的目录/mnt/sysroot  
function ROOTFS {# 使用函数实现各项功能,方便其他用户或者其他程序的调用,多写成函数,为以后着想哟! 
if [ -d $1 ];then 
  if mount | grep "$1" &> /dev/null ; then  #  判断我们的分区2是否正确的挂载了 
 cd $1 
 mkdir {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} -pv &> /dev/null #在这个目录里创建我们所需要用到的,各项文件夹。(麻雀虽小,五脏俱全嘛) 
 chmod 1777 tmp/
 
# create inittab  
cat >>$1/etc/inittab<< EOF  #创建inittab 写入如下的信息 
id:3:initdefault: 
si::sysinit:/etc/rc.d/rc.sysinit 
EOF 
 
# create rc.sysinit #创建rc.sysinit 写入如下的信息  
cat >>$1/etc/rc.d/rc.sysinit<< EOF 
#!/bin/bash  
echo -e "\t\tWelcome to \033[031;1mLittle\033[0m Linux..." 
 
mount -n -o remount,rw / 
mount -n -a 
 
/bin/bash 
EOF 
chmod +x etc/inittab   # 分别赋予他们执行的权限(你总不会想看到他们放在那却不能用吧-。-?) 
chmod +x etc/rc.d/rc.sysinit 
 
# create fstab   # 创建fstab 将我们到时候要挂载的分区信息写入。这里注意,一定是“到时候”要挂载的。  
cat >>$1/etc/fstab<< EOF 
/dev/sda2   /ext3defaults  0 0 
/dev/sda1   /bootext3defaults  0 0 
sysfs   /sys sysfs   defaults  0 0 
proc/procprocdefaults  0 0 
EOF 
  else 
read -p "Error,the $1 not mount ! Contiune(y|N)?" MOT   # 如果发现我们的分区2还没有挂上!就停止! 
case $MOT in# 不过这应该是不会没挂上的,否则我们上一步岂不是白做了!? 
y|Y) 
ROOTFS /mnt/sysroot  ;; 
*) 
echo "Exit......" 
return 5 
;; 
esac 
  fi 
fi 

 
ROOTFS /mnt/sysroot   # 最后,执行这个函数,传递给他一个/mnt/sysroot这个参数~~OK~ 

好的!我们完成了前三步!总结一下:

我们先按照用户选择的硬盘,将其分区,分成3块,然后都将其格式化。

之后我们把需要用到的分区挂载到我们设定的目录上去!

然后我们将分区内写入各项配置信息。

接下来,看第二篇啦~完成后面三个步骤!!OK,加油~换个页面,我们继续!

刚才我们已经完成了前三步的工作。我们再次对整个Shell脚本的实现方式进行一次分析:

实现过程分析:

1.分区,按照用户所选的盘,将其格式化,分区

2.挂载,按照用户设定的的分区好的盘分别挂载在我们宿主机的一个目录上。方便对微型linux进行编辑。

3.对微型Linux进行写入各项配置信息

4.将微型Linux中我们需要用到的Bash等命令放进去

5.放入内核,和启动必须加载的配置文件

6.对用户的硬盘安装引导程序。

----------------------------------------------------------------------------------------------------------

好的,刚才那算是帮助大家整理思路,算是“上集回顾”吧~接下来我们继续!将Shell脚本进行到底!

第四步:移植各种各样我们需要的命令进去:

脚本分析:

为了移植命令,我们就要先将我们宿主系统上的命令复制过去。
但是仅仅复制命令是不够的,我们还要将命令所对应的库文件复制过去。
那么,不同的命令有不同的样式,也有不同/相同的库文件。
我们就要辨别到底复制哪些库文件,复制到哪,有没有重复~
最后,我们要知道,不是仅仅复制一个命令就好,我们要循环的让用户选择到底需要什么命令。直到都复制结束~

好的,分析OK,我们按照计划着手去做吧!

function COPYLIB { # 我们依然使用函数,方便以后的调用工作。 
  #copy command  
  if which $1 &> /dev/null ;then # 判断用户输入的命令是否真的是个命令,总不能我们输入1,也复制1进去吧~=。= 
AA=`which $1 | tail -1 | awk '{print $1}'` 
cp "$AA" $2"$AA"  # 如果判断成功,则复制~ 
  else 
echo "$1 is not exist" 
  fi 
 
  #copy lib  #   开始复制命令对应的lib库文件  
  for LIB in `ldd "$AA" | grep "/lib/" | sed '1,$s@^[[:space:]]/lib@aaa=> /lib@g' | awk -F"=> " '{print $2}' | cut -d" " -f1`;do 
LIBPATH=`echo $LIB | sed <a>'s@\(.*\)/[^[:space:]]\{1,\}@\1@g'</a>`   # 我们用了一个for循环,来判断我们输入的命令所含的lib,并且将他们对齐,列表 
[ -d ${2}$LIBPATH ] || mkdir ${2}$LIBPATH  # 判断我们即将复制过去的目录是否存在,万一不存在则创建 
[ ! -e $2/$LIB ] && cp -f $LIB ${2}$LIBPATH && echo "$LIB done"  # 开始复制~并提示 复制的效果~~ 
  done 
 

# 到这里,这个函数就结束了,下面我们准备调用。首先要知道,有两个命令是必须复制的,一个是bash ,一个是 init ,两个都是非常非常重要的命令。  
echo "==========================================================" 
echo -e "Please input COMMAND with \033[31mbash\033[0m and \033[31minit\033[0m !!!!!" 
read -p "COMMAND you want?(Quit for 'q') :" CMD1  # 就是因为太重要,所以我们用上一条语句红色警示用户,必须先复制这两条。 
  # 然后我们制造一个循环,方便用户反复的加入各种各样的命令。  
until [ $CMD1 == 'q' ]; do# 当然,不能总是输入吧,所以我们只需要按 ‘q’ 
  COPYLIB $CMD1 /mnt/sysroot  # 执行函数 并且传递我们所输入的命令。 
  echo -e "Please input COMMAND with \033[31mbash\033[0m and \033[31minit\033[0m !!!!!" 
  read -p "Which COMMAND you want use ?(Quit for 'q') :" CMD1 
done 

OK~这样一来,我们的小linux里也有了各种各样我们所输入的命令啦~接下来,就要往里添加内核了!
让我们的linux运行起来!

第五步:弄个内核!让我们的Linux拥有心脏!

在手动打造属于自己的linux的时候,我们已经知道,我们的内核是直接用RedHat的内核文件。
然后再修改initrd这个能在内存中虚拟出一个小linux方便加载根目录系统的文件。
之后,我们将其移植进去就好。

接下来,我们开始做吧~!

function YDFQ {# 依然是函数-。- 
TMPDIR=`mktemp -d /tmp/little.XX`   # 创建一个临时文件夹,一会儿我们要解压initrd.*.img 用哦~ 
cd $TMPDIR 
zcat /boot/initrd-`uname -r`.img | cpio -id  &> /dev/null ## 在临时文件夹中解压并展开我们的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# 在init文件中注释掉我们没用的行~ 
 
sed -i "s@\(mkrootdev.*\) /.*@\1 sda2@" init# 改变init文件中有用的,比如我们要判断到时候执行哪个盘。 
find . | cpio -H newc -o --quiet | gzip -9 > /mnt/boot/initrd.gz# 重新归档并压缩成initrd.gz文件~ 
cp /boot/vmlinuz-`uname -r` /mnt/boot/vmlinuz # 将我们整理好的文件复制到我们的分区中去! 

YDFQ /mnt/sysroot# 函数执行的开始-。- 好吧,请原谅我总是将它写在后面  

ok~我们小linux的心脏也有了~接下来,就是最后一步了!!!给硬盘一个引导,让他知道自己该如何运行!

第六步:引导文件!

那么,既然需要引导,就又要提到我们伟大的 Grub了~ 它能直接给硬盘安装一个MBR进去~让其拥有boot loader~
这样一来,硬盘在开机启动之后就自己知道自己要做些什么了~~!
当然,我们的系统我们做主,所以里面要加上你自己的东西哟!!

开始动手吧!

## 这里我们要传递四个值到我们的函数中
## $1=我们要安装对哪个硬盘安装bootloader
## $2=我们的主分区,就是内核文件等所在的分区
## $3=内核的名字
## $4=initrd 的名字~  
##  
function GRUB { ## 好吧,各种各样的函数-。- 
if [ `basename $2` == boot ];then ## 判断用户输入的主分区是否是我们需要的主分区,不过这个肯定是了,因为下面我们手动指定了-。- 
  grub-install --root-directory=/mnt $1  &> /dev/null# 安装grub,到我们的分区去,这样我们就有了bootloader了! 
  cat >>$2/grub/grub.conf<< EOF # 制定我们自己的开机方式~~ 
default=0 
timeout=10 
title Little Linux 
root (hd0,0) 
kernel /${3} ro root=/dev/sda2 quiet 
initrd /${4} 
EOF 
 
else 
  echo "It's not boot !Exit & Please set it again !"  
fi 

 
GRUB $DSK /mnt/boot vmlinuz initrd.gz  # 好吧,函数开始执行了-。- 
 
echo "Congratulation ! Your Mini Linux is install OK !"   # 显示庆祝信息!告诉用户我们已经安装好了! 

OK~~!!!! 一切搞定~

接下来我们就去测试把~

按照这样的写下来,我们可以说基本实现了一键安装linux,并且是你自己制定的哟!!!!!

~

嗯~

看懂了么?会了么-。-那么,自己做做吧。