手把手带你自制Linux系统之三 添加关机重启及用户登录功能

手把手带你自制Linux系统之三 添加关机重启及用户登录功能

本章,要做的主要工作是为Mini Linux添加关机、重启功能及用户登录功能。

打开虚拟机中CentOS_5.5作为工作机,完成如下步骤:

1. 精简initrd文件 

上一章使用的initrd是直接从/boot/目录下拷贝的,没有做任何修改,这样做虽然比较简单,但会导致我们的MiniLinux体积比较大,启动速度慢等问题。这里对initrd文件进行一次精简。

initrd文件本身是一个gzip压缩文件
[root@localhost ~]# file /boot/initrd-2.6.18-164.el5.img
/boot/initrd-2.6.18-164.el5.img: gzip compressed data, from Unix, last modified: Thu Jul 23 18:46:14 2015, max compression

使用gzip解压initrd-2.6.18-164.el5.img文件,会得到initrd-2.6.18-164.el5.img
cp /boot/initrd-2.6.18-164.el5.img /boot/initrd-2.6.18-164.el5.img.gz
gzip -d initrd-2.6.18-164.el5.img.gz

得到的initrd-2.6.18-164.el5.img文件是一个cpio归档文件。
[root@localhost ~]# file initrd-2.6.18-164.el5.img
initrd-2.6.18-164.el5.img: ASCII cpio archive (SVR4 with no CRC)

使用cpio命令对它进行解归档 操作
cd /root
mkdir tmp
cd tmp
cpio -id < ../initrd-2.6.18-164.el5.img 

上面的gzip解压缩和cpio解归档操作可以合并为一条命令,做到一步到位 
cd /root
mkdir tmp
cd tmp
zcat /root/initrd-2.6.18-*.img.gz | cpio -id

编辑initrd中的init文件
vi init

注释掉一些用不到的行:

#!/bin/nash

mount -t proc /proc /proc
setquiet
echo Mounting proc filesystem
echo Mounting sysfs filesystem
mount -t sysfs /sys /sys
echo Creating /dev
mount -o mode=0755 -t tmpfs /dev /dev
mkdir /dev/pts
mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
mkdir /dev/shm
mkdir /dev/mapper
echo Creating initial device nodes
mknod /dev/null c 1 3
mknod /dev/zero c 1 5
mknod /dev/urandom c 1 9
mknod /dev/systty c 4 0
mknod /dev/tty c 5 0
mknod /dev/console c 5 1
mknod /dev/ptmx c 5 2
mknod /dev/rtc c 10 135
mknod /dev/tty0 c 4 0
mknod /dev/tty1 c 4 1
mknod /dev/tty2 c 4 2
mknod /dev/tty3 c 4 3
mknod /dev/tty4 c 4 4
mknod /dev/tty5 c 4 5
mknod /dev/tty6 c 4 6
mknod /dev/tty7 c 4 7
mknod /dev/tty8 c 4 8
mknod /dev/tty9 c 4 9
mknod /dev/tty10 c 4 10
mknod /dev/tty11 c 4 11
mknod /dev/tty12 c 4 12
mknod /dev/ttyS0 c 4 64
mknod /dev/ttyS1 c 4 65
mknod /dev/ttyS2 c 4 66
mknod /dev/ttyS3 c 4 67
echo Setting up hotplug.
hotplug
echo Creating block device nodes.
mkblkdevs
##echo "Loading ehci-hcd.ko module"
#insmod /lib/ehci-hcd.ko 
#echo "Loading ohci-hcd.ko module"
#insmod /lib/ohci-hcd.ko 
#echo "Loading uhci-hcd.ko module"
#insmod /lib/uhci-hcd.ko 
#mount -t usbfs /proc/bus/usb /proc/bus/usb
echo "Loading jbd.ko module"
insmod /lib/jbd.ko 
echo "Loading ext3.ko module"
insmod /lib/ext3.ko 
#echo "Loading scsi_mod.ko module"
#insmod /lib/scsi_mod.ko 
#echo "Loading sd_mod.ko module"
#insmod /lib/sd_mod.ko 
#echo "Loading scsi_transport_spi.ko module"
#insmod /lib/scsi_transport_spi.ko 
#echo "Loading mptbase.ko module"
#insmod /lib/mptbase.ko 
#echo "Loading mptscsih.ko module"
#insmod /lib/mptscsih.ko 
#echo "Loading mptspi.ko module"
#insmod /lib/mptspi.ko 
#echo "Loading libata.ko module"
#insmod /lib/libata.ko 
#echo "Loading ata_piix.ko module"
#insmod /lib/ata_piix.ko 
#echo "Loading dm-mod.ko module"
#insmod /lib/dm-mod.ko 
#echo "Loading dm-log.ko module"
#insmod /lib/dm-log.ko 
#echo "Loading dm-mirror.ko module"
#insmod /lib/dm-mirror.ko 
#echo "Loading dm-zero.ko module"
#insmod /lib/dm-zero.ko 
#echo "Loading dm-snapshot.ko module"
#insmod /lib/dm-snapshot.ko 
#echo "Loading dm-mem-cache.ko module"
#insmod /lib/dm-mem-cache.ko 
#echo "Loading dm-region_hash.ko module"
#insmod /lib/dm-region_hash.ko 
#echo "Loading dm-message.ko module"
#insmod /lib/dm-message.ko 
#echo "Loading dm-raid45.ko module"
#insmod /lib/dm-raid45.ko 
#echo Waiting for driver initialization.
#stabilized --hash --interval 1000 /proc/scsi/scsi
mkblkdevs
#echo Scanning and configuring dmraid supported devices
#echo Scanning logical volumes
#lvm vgscan --ignorelockingfailure
#echo Activating logical volumes
#lvm vgchange -ay --ignorelockingfailure  VolGroup00
#resume /dev/VolGroup00/LogVol01
echo Creating root device.
mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00
echo Mounting root filesystem.
mount /sysroot
echo Setting up other filesystems.
setuproot
echo Switching to new root and running init.
switchroot


删除lib下没用到的内核模块

删除/mnt/boot/initrd.img,并将/root/tmp下所有文件打包压缩为initrd.img,放在/mnt/boot/下 
rm /mnt/boot/initrd.img
find . | cpio -H newc  --quiet -o | gzip -9 > /mnt/boot/initrd.img

2. 拷贝命令脚本

上一章拷贝命令到Mini Linux系统时,需要把该命令依赖的动态链接库一并拷贝,做法是使用ldd命令查看命令,得到依赖库列表后,手动一个一个复制这些库文件。这样做不仅效率低,而且容易出错,命令较少时还好,一旦命令增多,缺点会非常明显。所以在开始本章内容前,完成一个脚本工具 - bincp.sh,用来拷贝命令及其依赖的动态链接库。脚本内容如下:

#!/bin/bash
#
DEST=/mnt/sysroot
libcp() {
  LIBPATH=${1%/*}
  [ ! -d $DEST$LIBPATH ] && mkdir -p $DEST$LIBPATH
  [ ! -e $DEST${1} ] && cp $1 $DEST$LIBPATH && echo "copy lib $1 finished."
}
 
bincp() {
  CMDPATH=${1%/*}
  [ ! -d $DEST$CMDPATH ] && mkdir -p $DEST$CMDPATH
  [ ! -e $DEST${1} ] && cp $1 $DEST$CMDPATH
 
  for LIB in  `ldd $1 | grep -o "/.*lib\(64\)\{0,1\}/[^[:space:]]\{1,\}"`; do
    libcp $LIB
  done
}
 
read -p "Your command: " CMD
until [ $CMD == 'q' ]; do
   ! which $CMD &> /dev/null && echo "Wrong command" && read -p "Input again:" CMD && continue
  COMMAND=` which $CMD | grep -v "^alias" | grep -o "[^[:space:]]\{1,\}"`
  bincp $COMMAND
  echo "copy $COMMAND finished."
  read -p "Continue: " CMD
done

有了这个脚本我们就可以轻松的拷贝命令呢,把一些常用的命令拷贝过去吧。

使用bincp.sh拷贝:ls, cd, cat, pwd 


3. 添加rc脚本

运行级别的原理:

1). 在目录/etc/rc.d/init.d下有许多服务器脚本程序

2). 在/etc/rc.d下有7个名为rcN.d的目录,对应系统的7个运行级别

3). rcN.d目录下都是一些符号链接文件,这些链接文件都指向init.d目录下的service脚本文件,命名规则为K+nn+服务名或S+nn+服务名,其中nn为两位数字

4). 系统会根据指定的运行级别进入对应的rcN.d目录,并按照文件名顺序检索目录下的链接文件

    对于以K开头的文件,系统将终止对应的服务

    对于以S开头的文件,系统将启动对应的服务


rc脚本所负责的正是原理4) 中服务的终止和启动。下面与一个简化版的rc脚本

vi /mnt/sysroot/etc/rc.d/rc

内容如下:

#!/bin/bash
#
runlevel=$1
for i in /etc/rc.d/rc$runlevel.d/K*; do
    $i stop
done
for i in /etc/rc.d/rc$runlevel.d/S*; do
    $i start
done

加上可执行权限:

chmod +x rc

修改inittab,指定在0和6运行级别时调用rc脚本,并且将运行级别作为参数。

vi etc/inittab

添加如下两行:

l0:0:wait:/etc/rc.d/rc 0
l6:6:wait:/etc/rc.d/rc 6

4. 添加关机重启功能

        shutdown命令被调用后会向所有运行中的程序发送SIGTEAM信号,告诉它们系统即将关闭。这个非常有用,比如vi在接收到SIGTEAM信号后可以及时保存正在编辑的文件。然后shutdown会发送信号给init进程,请求切换运行级别,0级别用来关闭系统,使用-h参数指定。6级别用来重启系统,使用-r参数指定。


根据运行级别的原理,0级别会在/etc/rc.d/rc0.d下检索并执行服务脚本文件,6级别对应的是/etc/rc.d/rc6.d。

rc0.d下的S01halt和rd6.d下的S01reboot链接同时指向/etc/rc.d/init.d/halt文件。

然后在halt文件中会调用halt或reboot命令,才能做到真正的关机和重启操作。


那么常用的关机重启命令还有halt, reboot,这三个命令有什么关系呢?


原来halt和reboot命令在运行级别不为0或6时执行,会被替换为shutdown -h或shutdown -r。运行级别为0或6时则不会被替换。

也就是说正常运行级别下,reboot和halt都要借助shutdown命令。


利用上面的bincp.sh复制这3个命令

shutdown,halt,reboot


完成halt

mkdir /mnt/sysroot/etc/rc.d/init.d/
vi /mnt/sysroot/etc/rc.d/init.d/halt

内容:

#!/bin/bash
case $0 in
    *halt)  
    COMMAND="/sbin/halt -p"
    ;;  
    *reboot)  
    COMMAND="/sbin/reboot"
    ;;  
    *)  
    echo echo "$0: call me as 'halt' or 'reboot' please!"
    ;;  
esac
exec $COMMAND

增加可执行权限:

chmod +x  /mnt/sysroot/etc/rc.d/init.d/halt

创建0和6级别对应的rcN.d目录,并且创建halt文件的链接

cd /mnt/sysroot/etc/rc.d/
mkdir rc0.d rc6.d
cd rc0.d
ln -s ../init.d/halt S01halt
cd rc6.d
ln -s ../init.d/halt S01reboot

5. 添加用户登陆验证功能

/bin/login: 依赖PAM,PAM过于复杂,这里我们绕过PAM,实现不基于PAM的认证。
需要重新编译login,生成一个不依赖PAM的login程序。

ldd 查看重新编译的login所依赖的库文件,
[root@localhost bin]# ldd login
linux-gate.so.1 =>  (0xffffe000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x0040d000)                 
libm.so.6 => /lib/libm.so.6 (0xf7edf000)
libc.so.6 => /lib/libc.so.6 (0x002b1000)
/lib/ld-linux.so.2 (0x00293000)

复制这些库
cp /lib/libcrypt.so.1 /mnt/sysroot/lib/libcrypt.so.1
cp /lib/ /lib/libm.so.6  /mnt/sysroot/lib/libm.so.6 
cp /lib/ /lib/libc.so.6   /mnt/sysroot/lib/libc.so.6

login程序需要借助nsswitch(Network Service Switch)来找到账号密码应该在什么地方, nsswitch的配置文件/etc/nsswitch.conf中定义了服务搜索顺序。

复制nss依赖库:

cp -d /lib/libnss_files* /mnt/sysroot/lib/
cp -d /usr/lib/libnss3.so /usr/lib/libnssckbi.so /usr/lib/libnssutil3.so /mnt/sysroot/usr/lib/


拷贝并编辑nsswitch.conf文件

cp /etc/nsswitch.conf /mnt/sysroot/etc/
vi /mnt/sysroot/etc/nsswitch.conf

保留下面这4行即可

 33 passwd:     files
 34 shadow:     files
 35 group:      files
 38 hosts:      files dns</span>

添加passwd, shadow, gourp这3个文件

grep "^root\>" /etc/passwd > /mnt/sysroot/etc/passwd
grep "^root\>" /etc/shadow> /mnt/sysroot/etc/shadow
grep "^root\>" /etc/group> /mnt/sysroot/etc/group

修改inittab文件,

vi /mnt/sysroot/etc/inittab

指定2345运行级别时启动mingetty,mingetty会调用/bin/login验证用户:

1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2

移植命令:mingetty


去掉/mnt/sysroot/etc/rc.d/rc.sysinit中的/bin/bash,仅保留:

#!/bin/bash
echo -e "\tWelcome to \033[31mMy MiniLinux\033[0m."

添加终端提示符
vi /mnt/sysroot/root/.bash_profile

添加内容
export PS1='[\u@\h \W]\\$ '
其中\u等符号会分别被替换
\u - user,用户名
\h - hostname,主机名
\W - current path,当前路径
\\$ - 提示符,root 为#,其它为$

6. 测试

挂起正在使用的工作机,切换到虚拟机中MiniLinux,并开机,过几秒后出现login提示符,使用root账户登录(密码同工作机中root密码)后如图所示,说明前面的几步都是没有问题的:


7. 总结

本章为MiniLinux添加了关机重启功能,终于可以使用命令进行关机和重启,而不是点击vmware中的按钮。用户登录验证的添加,只有拿到用户密码才可以使用MiniLinux,增强了系统的安全性。一些常用命令的添加增加了它的实用性。但是,现在的系统只能看,不能动,因为文件系统是以只读方式挂载的,一切对文件系统的写操作都是不允许的,下一章将要解决的就是这个问题。


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值