Linux15 linux启动流程详解及系统制作

Linux启动流程

PC:OS(Linux)

POST(加电自检)-->BIOS(Boot Sequence)-->MBR(bootloader,446)-->Kernel-->initrd(ROOTFS)-->/sbin/init(/etc/inittab)

启动的服务不同:
	运行级别:0-6
	0:halt # 关机
	1:single user mode,直接以管理员身份切入
	2: multi user mode,不启用 NFS
    3:multi user mode,多用户下的文本模式(text mode)
    4:reserved 保留级别
    5:multi user mode,graphic mode
    6:reboot
内核设计风格:
单内核:Linux(LWP  light weight process)
	核心:ko(kernel object)
微内核:Windows,Solaries
Redhat SUSE
核心:动态加载  内核模块
内核: /lib/modules/"内核版本号命令的目录"/  #  3.10.0-1160.21.1.el7.x86_64  3.10.0-957.el7.x86_64

Redhat5:ramdisk-->initrd
Redhat6:ramfs-->initramfs


详解启动过程

bootloader(MBR)

# 第一种
LILO:Linux Loader,不能引导1024柱面以后分区的Linux内核,所以不支持大硬盘。在嵌入式系统比较好用

# 第二种
GRUB:Grand Unified Bootloader
	Stage1:被装在在MBR
	Stage1_5
	Stage2:/boot/grub/
	
grub.conf

default=0 # 设定默认启动的title的编号,从0开始
timeout=5 # 等待用户选择的超时时长,单位是秒
splashimage=(hd0,0)/grub/splash.xpm.gz  # grub的背景图片
hiddenmenu  # 隐藏菜单
# password redhat
password --md5 # 使用grub-md5-crypt 生成加密密码
title Red Hat Enterprise Linux Server (2.6.18-308.el5)  # 内核标题,或操作系统名称,字符串,可自由修改
	root (hd0,0)  # 内核文件所在的设备;对grub而言,所有类型硬盘一律hd;格式为(hd#,N); hd#, # 表示第几个磁盘;最后的n表示对应磁盘的分区;
	kernel /vmlinuz-2.6.18-308.el5 ro root=/dev/vo10/root-rhgb quiet # 内核文件路径,及传给内核的参数  cat /proc/cmdline 查看内核参数
	initrd /initrd-2.6.18-308.el5.img  # ramdisk文件路径
title Install Red Hat Enterprise Linux 5
	root (hd0,0)
	kernel /vmlinuz-5 ks=http://192.16.0.1/workstation.cfg ksdevive=eth0 noipv6
	initrd /initrd-5
	password --md5 $1$FSUEU/$uhUUc8USBK5QAXc.BfW4m.

查看运行级别

runlevel  # 
N  3  # N表示没有切换过,3表示运行在第三个级别

who -r  # 也可以显示运行级别

查看内核版本号

uname -r  # 查看内核版本号

grub损坏之后的修复

# 安装grub stage1:
# grub
grub> root (hd0,0)
grub> set (hd0)

# 安装grub第二种方式
# grub-install --root-directory=/path/to/boot's_parent_dir /PATH/TO/DEVICE


grub> find
grub> root (hd#,N)
grub> kernel /PATH/TO/KERNEL_FILE
grub> initrd /PATH/TO/INITRD_FILE
grub> boot

Kernel初始的过程:
1.设备探测
2.驱动初始化(从initrd(initramfs)文件中装载驱模块)
3.以只读挂载根文件系统;
4.装载第一个进程init(PID:1)

/sbin/init: (/etc/inittab)
	upstart;ubuntu,d-bus,event-driven
	systemd;


# ACTION:
initdefault: 设定默认运行级别
sysinit:系统初始化
wait:等待级别切换至此级别时执行
respawn:一旦程序终止,会重新启动;

id:runlevels:action:process
id:标识符
runlevels:在哪个级别下运行此行
action:在什么情况下执行此行
process:要运行程序;


/etc/rc.d/rc.sysinit完成的任务;
1.激活udev和selinux;
2.根据/etc/sysctl.conf文件,来设定内核参数;
3.设定时钟;
4.装载键盘映射;
5.启用交换分区;
6.设置主机名;
7.根文件系统检测,并以读写方式重新挂载;
8.激活RAID和LVM设备;
9、启用磁盘配额;
10、根据/etc/fstab,检查并挂载其他文件系统;
11、清理过期的锁和PID文件;

id:5:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit
OS初始化
10:0:wait:/etc/rc.d/rc 0
	rc0.d/
		K*
			stop
		S*
			start

/etc/rc.d/init.d,/etc/init.d
服务类脚本:
	start
	
	SysV: /etc/rc/d/init.d
		start | stop | restart | status | reload | configtest

# chkconfig命令:管控/etc/init.d下每个服务脚本在各个级别下的启动和关闭状态
能被添加为服务的脚本定义格式:
  #!/bin/bash
  #
  # chkconfig:
  # description

# chkconfig: runlevels SS KK
runlevels: -表示, 没有级别默认为S*开头的链接
	当chkconfig命令来为此脚本在rc#.d目录创建链接时,runlevels表示默认创建为S*开头的链接,除此之外的级别默认创建为K*开头的链接;S后面的启动优先级为SS所表示的数字;K后面关闭优先次序为KK所表示的数字;
# description: 用于说明此脚本的简单功能; , 续行

chkconfig --list 显示所有独立守护服务的启动设定;独立守护进程!
chkconfig --list SERVICE_NAME 显示某个服务
	chkoconfig --list network
chkconfig --add SERVICE_NAME  添加到chkconfig可以控制的服务列表中

chkconfig --del myservice

chkconfig --level RUNLEVELS SERVICE_NAME {on|off}
	如果省略级别指定,默认为2345级别;
chkconfig --level 24 myservice off
#!/bin/bash
#
# chkconfig:2345 77 22
# description: Test Service
#
LOCKFILE=/var/lock/subsys/myservice
status() {
  if [ -e $LOCKFILE ];then
	echo "Running..."
  else
	echo "Stopped." 
  fi
}

usage() {
echo "`basename $0` {start|stop|restart|status}"
}
case $1 in
start)
	echo "Starting..." 
	touch $LOCKFILE ;;
stop)
	echo "Stopping..." 
	rm -f $LOCKFILE &>/dev/null ;;
restart)
	echo "Restarting..." ;;
status)
	status ;;
*)
	usage ;;
esac

文件中没有 # chkconfig  # description 这两行,chkconfig -add 无法将此文件添加到服务列表中去

/etc/rc.d/rc.local:系统最后启动的一个服务,准确说,应该执行的一个脚本;

# redhat5上:
/etc/inittab的任务:
1.设定默认运行级别;
2.运行系统初始化脚本;
3.运行指定运行级别对应的目录下的脚本;
4.设定Ctrl+Alt+Del组合键的操作;
5.定义UPS电源在电源故障/恢复时执行的操作;
6.启动虚拟终端(在2345级别);
7.启动图形终端(5级别);

守护进程的类型

独立守护进程
xinetd:超级守护进程,代理人
	瞬时守护进程:不需要关联至运行级别
	
设定内核参数数值的方法:
echo VALUE > /proc/sys/TO/SOMEFILE
sysctl -w kernel.hostname=  # 或者 echo "" > /proc/sys/net/ipv4/ip_forward || /proc/sys/vm/drop_caches || /proc/sys/kernel/hostname
能立即生效,但无法永久有效;
永久有效:/etc/sysctl.conf

修改文件完成之后,执行如下命令可立即生效:
sysctl -p
sysctl -a : 显示所有内核参数及其值

内核模块管理:
lsmod  # 查看内核装载了哪些模块
modprobe MOD_NAME # 装载某个模块
modprobe -r MOD_NAME #卸载某个模块
modinfo MOD_NAME # 查看模块的具体信息

insmod /path/to module_file # 装载模块

mrmod MODE_NAME  # 移除模块
depmod /path/to/modules_dir

内核中的功能除了核心功能之外,在编译时,大多功能都有三种选择:
1.不使用此功能;
2.编译成内核模块;
3.编译进内核;


# 如何手动编译内核:
make gconfig:Gnome 桌面环境使用,需要安装图形开发库组:GNOME Software Development
make kconfig:KDE桌面环境使用,需要安装图形开发库

makemenuconfig
make
make modules_install
make install



screen命令:
screen -ls:显示已经建立的屏幕
screen:直接打开一个新的屏幕
	Ctrl+a,松开后按d:拆除屏幕  # 拆除后可以根据screen -r ID 再次进入这个屏幕
screen -r ID:还原回某个屏幕
exit: 退出屏幕

二次编译时清理,清理前,如果有需要,请备份配置文件.config;
make clean # 清理此前编译好的二进制模块
make mrproper # 清理此前编译所残留的操作,

grub-->kernel-->initrd-->ROOTFS(/sbin/init,/bin/bash)

mkinitrd initrd文件路径  内核版本号
mkinitrd /boot/initrd-`uname -r`.img `uname -r`

chroot /mnt/sysroot  # 切换到另一个系统
vim etc/rc.d/rc/sysinit
#!/bin/bash
#
echo -e "	Welcome to 33[31m mini system33[0m linux."
insmod /lib/modules/mii.ko
insmod /lib/modules/pcnet32.ko
ifconfig ens1 172.16.100.13/16
ifconfig lo 127.0.0.1/8
/bin/bash

:wq

sync

$(parameter#*word) # 从左往右匹配,找到第一个'/',将/及其左边的内容全部去掉
$(parameter##*word) # 从左往右匹配,找到最后一个'/',将/及其左边的内容全部去掉

FILE=/usr/local/src
$(FILE#*/):usr/local/src 
$(FILE##*):src  

$(parameter%word*)  # 从右往左匹配,找到第一个'/',将/及其右边的内容全部去掉
$(parameter%%word*)  # 从右往左匹配,找到最后一个'/',将/及其右边的内容全部去掉
$(FILE%*/):/usr/local
$(FILE%%*/)

制作小系统中命令:拷贝每个命令的二进制文件及二进制文件所依赖的库文件

#!/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 && 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

计算机加电之后,系统将ram中的程序映射到CPU可以寻址的某个空间中去,并且CPU执行其中的指令,这些指令完成系统检测,当检测基本硬件或者核心硬件没有问题,进入下一步;
根据BIOS(Boot Sequence)内设定的系统启动流程找对应存储设备上的MBR,如果MBR存在,就会读取MBR中的bootloader(一段程序,MBR留给bootloader的空间是512个字节,但用于bootloader的有446个字节),在bootloader中配置了所要引导的操作系统内核的位置,当BIOS载入内存以后,当他实现将控制流程(控制权限)转交给bootloader以后,bootloader就接受到了整个系统的控制权限,而后根据用户的选择,读取相应操作系统的内核(kernel),将内核装载在内存合适的位置,解压缩,并完成内核初始化以后,bootloader会将控制权限转交给内核;
	kernel(initrd(rehl5),initramfs(rehl6)),initrd里面有我们内核所依赖的其他设备驱动,尤其是根文件系统的驱动;
	
内核初始化的时候需要完成哪些工作:
硬件探测
装载驱动
挂载根文件系统(rootfs)
启动用户空间中的第一个进程init

内核要完成初始化,需要依赖驱动程序,如果这些驱动程序没有被做在内核当中的话,就需要到某个文件按系统的路径下去装载这个驱动程序,而在跟文件系统被挂载之前,就出现了一个难题,如果内核访问根文件系统中的某个设备需要某个驱动程序的话,内核中没有该驱动,它就需要到根文件系统去找这个驱动程序,而这个根文件系统又没挂载,所以要想访问文件系统,得先找到驱动;要想访问驱动,得先找到文件系统,所以出现一个难题。这时就借助于initrd为内核提供访问根文件系统所需要的基本驱动程序,initrd将内核和根文件系统连接起来了,接下来执行init程序(/etc/inittab,RHEL6:upstart) 
	upstart -->init
		/etc/inittab
			设定默认运行级别
			系统初始化(/etc/rc.d/rc.sysinit)
			运行指定级别的服务脚本
				/etc/rc.d/init.d
					/etc/rc.d/rc#.d
						rc0.d--rc6.d
							K*
							S*
								00-99:运行次序,数字越小,越先被执行
			启动虚拟终端
             启动图形终端

/etc/rc.d/rc.sysinit:
    内核在装载根文件系统时,为了避免根文件系统被损坏,以只读方式挂载根文件系统;
    定义主机名;
    检测并挂载/etc/fstab中的其他文件系统;
    启动swap分区;
    初始化外围硬件设备的驱动,包括CPU,内存。 而网卡、显卡等是由init程序驱动
    根据/etc/sysctl.conf设定内核参数;
    激活udev和selinux;
    激活LVM和RAID设备;
    清理过期锁和PID文件;
    装载键映射;

/etc/inittab
id:3:initdefault:
si:sysinit:/etc/rc.d/rc.sysinit

/etc/rc.d/rc.sysinit
echo
insmod
ifconfig
/bin/bash


		/etc/init/*.conf
shutdown # 根据指定得参数关机或重启
halt # 关机
reboot # 重启
poweroff # 关机

init 0  # 关机
init 6  # 重启

1.关机和重启;
2.主机名;
3.运行对应服务脚本;
4.启动终端;
5.运行用户;
6.定义单用户级别;
7.装载网卡驱动,启用网络功能;
8、提供一个web服务器;

busybox:1M
Kernel:

RHEL5,RHEL6
定制安装:	
	自动化安装
	定制引导盘

mount 
  /dev/hda1  on  /mnt/boot  type ext3 (rw)
  /dev/hda2  on /mnt/sysroot  type ext3 (rw)

tree /mnt

cp /boot/vmlinuz-2.6.18-308.el5 /mnt/boot/vmlinuz
cd
mkdir test
cd test/
zcat /boot/initrd-2.6.18-308.el5.img | cpio -id
ls
vim init

cd lib/
rm -f dm-*
cd ..
ls
find . | cpio -H newc --quiet -o | gzip -9 > /mnt/boot/initrd.gz

ls -lh /mnt/boot/

grub-install --root-directory=/mnt /dev/hda  # 安装grub

ls /mnt/boot  # grub文件已经生成
vim /mnt/boot/grub/grub.conf

    default=0
    timeout=3
    title ZhangChang Linux(2.6.18)
        root(hd0,0)
        kernel /vmlinuz
        initrd /initrd.gz
# 提供根文件系统
cd /mnt/sysboot
mkdir -p etc/rc.d/init.d bin sbin proc sys dev lib root mnt media var/{log,run,lock/subsys} usr/{bin,sbin,local} tmp home opt boot
'''
etc/{rc.d/init.d} bin sbin proc sys dev lib是核心的不可以单独分区,mnt media也不可以单独分区但不是核心;home var 可以单独分区;root是管理员的家目录,不可以单独分区;
'''

vim etc/inittab
    id:3:initdefault:
    si::sysinit:/etc/rc.d/rc.sysinit

vim etc/rc.d/rc.sysinit
    #!/bin/bash
    #
    echo -e "	Welcome to 33[34mZhangChao33[0m Linux"
    /bin/bash
chmod +x etc/rc.d/rc.sysinit

# 移植可执行程序 最核心的有2个  init  bash

./bincopy.sh
	init 
	bash
	ls
	touch
	mkdir
	rm 
	mv
	cp
	cat
	mount
	umount
	vim 
	chmod
	chown
	ping
	ifconfig
	insmod
	modprobe
	rmmod
	route
	halt
	reboot
	shutdown
	hostname
	
sync # 将拷贝的数据同步到磁盘上 可以多sync几下
chroot /mnt/sysroot

创建新的虚拟机,并选择刚刚制作的

touch /tmp/a.txt
# touch:cannot touch '/tmp/a.txt':Tead-only file system
mount -o remount,rw /
	can't create lock file /etc/mtab~521:Read-only file system (use -n fila to override)
mount -n -o remount,rw /
	warning:can't open /etc/fstab:No such file or directory EXT3 FS on hda2,internal journal
touch /tmp/a.txt

halt # 执行关机命令,只能关掉进程,但是无法切断电源
	INIT:Switching to runlevel:0
	INIT:Sending processes the TERM signal
	INIT: no more processes left in this runlevel
halt -p # 关机并切断电源,因为该命令是在bash中进行的,所以halt是父进程(bash)的子进程,halt只能关掉子进程,对父进程没有影响;可以使用exec,让子进程去替换父进程,而不是作为子进程去运行,这样halt运行结束,bash 也就结束了。
exec halt -p # 表示用exec启动halt命令,并替换bash命令。
	INIT:Switching to runlevel:0 # 执行此命令,还需要切换到对应级别下,把halt命令添加到可执行文件。
	INIT:Sending processes the TERM signal
	INIT: no more processes left in this runlevel

cd /mnt/sysroot
vim etc/rc.d/rc.sysdone
    #!/bin/bash
    #
    sync
    sleep 2
    sync
    exec /sbin/halt -p
    sync

chmod +x etc/rc.d/rc.sysdone

./bincp.sh
    sync
    sleep

cd /mnt/sysroot
vim etc/inittab
    id:3:initdefault:
    si::sysinit:/etc/rc.d/rc.sysinit
    
    l0:0:wait:/etc/rc.d/rc.sysdone

虚拟机下,开机小系统
能正常运行

init 0 # 小系统能正常关机了

现在系统还不能重启,可以在inittab文件中再编辑reboot
vim etc/inittab
	id:3:initdefault:
    si::sysinit:/etc/rc.d/rc.sysinit
    
    l0:0:wait:/etc/rc.d/rc.sysdone
    l6:6:wait:/etc/rc.d/rc.reboot

vim etc/rc.d/rc.reboot
    #!/bin/bash
    #
    sync
    sleep 1
    sync
    exec /sbin/reboot
 
 mount -n -o remount,rw /
chmod +x etc/rc.d/rc.reboot

init 6 # 测试小系统能不能重启






mount -n # 挂载时不更新/etc/mtab文件;
cat /proc/mounts  # 显示系统上挂载的所有文件系统

一个脚本实现小系统的关机和重启

vim etc/rc.d/init.d/halt

#!/bin/bash
#
case $0 in
*reboot)
  COMMAND='/sbin/reboot' ;;
*halt)
  COMMAND='/sbin/halt -p' ;;
*)
  echo "Only call this script by *reboot OR *halt;" ;;
esac
case $1 in
start)
;;
stop)
;;
*)
  echo "Usage:`basename $0` {start| stop}" ;;
esac
exec $COMMAND


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

cd etc/rc.d
ls init.d/  # halt
mkdir rc0.d rc6.d
cd rc0.d/
ln -sv ../init.d/halt S99halt
ll 
	lrwxrwxrwx 1 root root 14 Mar 27 13:04 S99halt  -> ../init.d/halt
cd rc6.d/
ln -sv ../init.d/halt S99reboot
cd ..
ls
'''
init.d rc0.d rc6.d rc.reboot rc.sysdone rc.sysinit
'''
rm -f rc.reboot rc.sysdone
sync

vim rc
    #!/bin/bash
    #
	RUNLEVEL=$1
    for I in /etc/rc.drc$RUNLEVEL.d/K*;do
      $I stop
    done

    for I in /etc/rc.d/rc$RUNLEVEL.d/S*;do
      $I start
    done

chmod +x rc

vim /etc/inittab
	id:3:initdefault:
    si::sysinit:/etc/rc.d/rc.sysinit
    
    l0:0:wait:/etc/rc.d/rc 0
    l6:6:wait:/etc/rc.d/rc 6

init 6 # 重启
init 0 # 关机

# 在级别3下启动服务
vim etc/inittab
	l3:3:wait:/etc/rc.d/rc 3

cd etc/rc.d/
mkdir rc3.d
vim init.d/tserver

#!/bin/bash
#
# chkconfig: 35 66 33
# description: test service script
#
. /etc/rc.d/init.d/functions  # 相当于source 或者include引入函数(库)的意思,只不过在shell中这么写而已
prog=tserver
lockfile=/bar/lock/subsys/$prog
start() {
  touch $lockfile
  [ $? -eq 0 ] && success "Starting $prog"  || failure "Starting $prog" # 上面已经将functions文件中的函数已经加载进来,这里可以调到
}
stop() {
  rm -f $lockfile
  [ $? -eq 0 ] && success "Stopping $prog" || failure "Starting $prog"
}
status() {
  if [ -f $lockfile ];then
    echo "Running..."
  else
    echo "Stopped..."
  fi
}

usage() {
  echo "Usage: $prog {start|stop|status|restart}"
}
case $1 in 
start)
  start ;;
stop)
  stop ;;
restart)
  stop
  start
  ;;
status)
  status 
  ;;
*)
  usage
  exit 1
  ;;
esac
 
  
cd rc3.d/
ln -sv ../init.d/tserver S66tserver
cd rc0.d/
ln -sv ../init.d/tserver K33server

vim /etc/inittab
1:2345:respawn:/sbin/mingetty --loginprog=/bin/bash tty1
2:2345:respawn:/sbin/mingetty --loginprog=/bin/bash tty2

vim rc.d/rc.sysinit
	删除 /bin/bash


./bincp.sh
	mingetty
	basename

vim /etc/fstab
/dev/hda2		/		ext3		defaults		0  0
/dev/hda1		/boot	ext3		defaultss		 0  0
/proc			/proc	proc		defaults		0  0
sysfs			/sys	sysfs		defaults		0  0


vim etc/rc.d/rc.sysinit
	echo -e "	Welcome to 33[31m mini system33[0m linux."
	echo "Recount rootfs..."
	mount -n -o remount,rw /  # 根文件系统重新挂载

# 给小系统添加主机名
vim etc/rc.d/rc.sysinit
mkdir etc/sysconfig
vim etc/sysconfig/network
HOSTNAME=chao.zhang.com

# 在rc.sysinit文件中添加主机名
vim etc/rc.d/rc.sysinit
	echo -e "	Welcome to 33[31m mini system33[0m linux."
	echo "Recount rootfs..."
	mount -n -o remount,rw /  # 根文件系统重新挂载
	
	echo "Set the hostname..."
	[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network  # .命令读取文件
	[ -z $HOSTNAME -o "$HOSTNAME"  == '(none)' ] && HOSTNAME=localhost
	/bin/hostname $HOSTNAME

修改开机后不需要用户输入密码

stty -F /dev/console speed  # 查看控制台每秒钟输出的字符数

./bincp.sh
	agetty
cd /mnt/sysroot
vim etc/inittab
	id:3:initdefault:
    si::sysinit:/etc/rc.d/rc.sysinit
    
    l0:0:wait:/etc/rc.d/rc 0
    l3:3:wait:/etc/rc.d/rc 3
    l6:6:wait:/etc/rc.d/rc 6
    
    1:2345:respawn:/sbin/agetty -n -l /bin/bash 38400 tty1
    2:2345:respawn:/sbin/agetty -n -l /bin/bash 38400 tty2

启动小系统
	报错:INIT:No inittab file found # 文件系统因为来回地切换,导致错乱
修复文件系统:可以将 /mnt/sysroot下的文件打包放到其他目录,等到文件系统修复再导回来。
cd /mnt/sysroot/
find . | cpio -H newc --quiet -o | gzip > /root/sysroot.gz
cd
umount /dev/hda2
	umount: /mnt/sysroot:device is busy
fuser -km /dev/hda2
umount /dev/hda2
mke2js -j /dev/hda2  # 磁盘分区过后的格式化磁盘
mount /dev/hda2 /mnt/sysroot
cd /mnt/sysroot
zcat /root/sysroot.gz | cpio -id
sync
sync

启动小系统:
	报错:INIT:No inittab file found 
cd /mnt/sysroot
find . | cpio -H newc --quiet -o | gzip > /root/sysroot.gz
cd 
fuser -km /mnt/sysroot
umount /dev/hda2
e2fsck -f /dev/hda2  # 用于检查使用 Linux ext2 档案系统的 partition 是否正常工作
mount /dev/hda2 /mnt/sysroot/
cd /mnt/sysroot
vim etc/inittab  # 查看文件内容是否丢失,发现没丢失;如果丢失,继续执行mke2js命令

启动小系统  # 一切正常

红帽系统启动时控制台信息输出OK格式编辑


# A="Starting tserver"
# echo ${#A} #  在一个变量前加井号,表示取字符串的长度;

stty -F /dev/console size  # 显示物理终端屏幕的大小
	25 80  # 表示25行,80列
stty -F /dev/console size | cut -d' ' -f2
# stty -F /dev/console size | awk '{print $2}'

A=`stty -F /dev/console size`
echo $A
echo ${A#* } # 从左往右找到第一个以空格为分隔符的,把空格左边的全部去掉
echo ${A##* } # 从左往右找到最后一个以空格为分隔符的,把空格左边的全部去掉

/etc/init.d/functions  # 定义了一堆函数,文件中函数让公共脚本所需要用到的功能通过函数的方式来实现
如何让系统再启动的时候,服务脚本成功的时候显示为 绿色 [ OK ] 失败的时候显示为红色的 [ failed ]  ?

cd /mnt/sysroot
vim etc/rc.d/init.d/functions  # 里面只有函数,不需要自己执行,是别的脚本调用执行(载入执行)的,没有任何的主程序,所以不需要 #!/bin/bash


#!/bin/bash
#
SCREEN=`stty -F /dev/console size &> /dev/null`
COLUMNS=${SCREEN#*}
[ -z $COLUMNS ] && COLUMNS=80
SPA_COL=$[$COLUMNS-14]

RED='33[31m'
GREEN='33[32m'
YELLOW='33[33m'
BLUE='3334m'
NORMAL='33[0m'

success() {
  string=$1
  RT_SPA=$[$SPA_COL-${#string}]
  echo -n "$string"
  for I in `seq 1 $RT_SPA`;do
    echo -n " "
  done
  echo -e "[  ${GREEN}OK${NORMAL}  ]"
}

failure() {
  string=$1
  RT_SPA=$[$SPA_COL-${#string}]
  echo -n "$string"
  for I in `seq 1 $RT_SPA`;do
    echo -n " "
  done
  echo -e "[  ${RED}FAILED${NORMAL}  ]"
}

# success "starting tserver"
# failure "starting tserver"
chmod +x etc/rc.d/init.d/functions

修改上面的/etc/rc.d/init.d/tserver 文件

chroot /mnt/sysroot
/etc/rc.d/init.d/tserver/ start
	报错:/etc/rc.d/init.d/functions:line 1:stty:command not found

exit
/root/bincp.sh
	seq
	stty
chroot /mnt/sysroot
	报错:stty:/dev/console:No such file or directory
exit
修改/etc/rc.d/init.d/tserver脚本
chroot /mnt/sysroot
/etc/rc.d/init.d/tserver/ start  # 正常执行脚本
/etc/rc.d/init.d/tserver/ stop  # 正常执行脚本

重新启动小系统
	报错:
		EXT3-fs error (device hda2):ext3_lookup: unlinked inode 89087 in dir #89071 Aborting journal on device hda2.
		/etc/rc.d/rc:line 10:/etc/rc.d/rc3.d/S66tserver:No such file or directory ext3_abort called.
		EXT3-fs errot (device hda2):ext3_journal_start_sb:Detected aborted journal Remounting  filesystem read-only

cd /mnt/sysroot/
find . | cpio -H newc --quiet -o | gzip > /root/sysroot.2.gz
cd
fuser -km /mnt/sysroot
umount /mnt/sysroot
e2fsck -f /dev/hda2

mke2fs -j /dev/hda2
mount /dev/hda2 /mnt/sysroot
zcat /root/sysroot.2.gz | cpio -id
sync
sync
sync


重新启动小系统 # 一切正常
init 0  # 关机

给小系统添加ip地址

cd /mnt/sysroot
mkdir lib/modules
modinfo pcnet32
cp /lib/modules/3.10.0-1160.21.1.el7.x86_64/kernel/drivers/net/ethernet/amd/pcnet32.ko.xz
 /mnt/sysroot/lib/modules/
modinfo mii
cp /lib/modules/3.10.0-1160.21.1.el7.x86_64/kernel/drivers/net/mii.ko.xz /mnt/sysroot/lib/modules/

vim etc/rc.d/rc.sysinit
	echo -e "	Welcome to 33[31m mini system33[0m linux."
	echo "Recount rootfs..."
	mount -n -o remount,rw /  # 根文件系统重新挂载
	
	echo "Set the hostname..."
	[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network  # .命令读取文件
	[ -z $HOSTNAME -o "$HOSTNAME"  == '(none)' ] && HOSTNAME=localhost
	/bin/hostname $HOSTNAME
	
	echo "Initializing network device..."
	/sbin/insmod /lib/modules/mii.ko
	/sbin/insmod /lib/modules/pcnet32.ko

# 自己写一个network的脚本
mkdir -pv etc/sysconfig/network-scripts
vim etc/sysconfig/network-scripts/ifcfg-ens33
    DEVICE=ens33
    BOOTPROTO=static
    IPADDR=172.16.100.5
    NETMASK=255.255.0.0
    GATEWAY=172.16.0.1
    ONBOOT=yes

vim etc/rc.d/init.d/network


vim etc/rc.d/init.d/network
#!/bin/bash
#
# chkconfig: 35 09 90
# description: network service
prog=network
. /etc/rc.d/init.d/functions
CONF=/etc/sysconfig/network-scripts/ifcfg-ens33
. $CONF
NETMASK=16

usage() {
  echo "$prog:{start|stop|restart|status}"
}
start() {
  ifconfig ens33 $IPADDR/$NETMASK up
  [ -z $GATEWAY ] && route add default gw $GATEWAY
  return 0
}
stop() {
  ifconfig ens33 down
}
status() {
  ifconfig ens33
}

case $1 in
start)
  start
  success "Config network ens33"
  ;;
stop)
  stop
  success "Stop network card ens33"
  ;;
restart)
  stop
  start
  success "Restart network card ens33"
  ;;
status)
  status
  return 0
  ;;
*)
  usage
  exit 1
  ;;
esac

chmod +x etc/rc.d/init.d/network

为了能让小系统能在级别3下启动,级别6和级别0下能够关机,需要创建连接
cd etc/rc.d/rc0.d/
ln -sv ../init.d/network K90network
cd ../rc6.d/
ln -sv ../init.d/network K90network
cd ../rc3.d/
ln -sv ../init.d/network S09network

chroot /mnt/sysroot
etc/rc.d/init.d/network stop
	报错

cd /mnt/sysroot
find . | cpio -H newc --quiet -o | gzip > sysroot.3.gz
cd
fuser -km /dev/hda2
umount /dev/hda2
mke2fs -j /dev/hda2
mount /dev/hda2 /mnt/sysroot
cd /mnt/sysroot
zcat /root/sysroot.3.gz | cpio -id
cd lib/modules/
ls
  mii.ko  pcnet32.ko
sync
sync

登录终端前屏幕信息

/etc/issue
	
:显示的是uname -r的信息
	m:显示的是uname -m的信息
	可以通过mingetty命令查看

cp /etc/issue /mnt/sysroot/etc
vim issue
    zhangchao Linux
    Kernel 
 on an m
    http://www.chaozhang.com

rc.sysinit:挂载/etc/fstab中定义的其它文件系统

除了根文件系统和swap

一个文件系统如果被挂载,一定会出现在/proc/mounts文件中
grep -E -v "<swap|proc|sysfs>" /etc/fstab | awk '{print $1}' | while read LINE;do awk '{pirnt $1}' /proc/mounts | grep "^$LINE$"; done

vim etc/rc.d/rc.sysinit
	echo -e "	Welcome to 33[31m mini system33[0m linux."
	
	echo "Recount rootfs..."
	mount -n -o remount,rw /  # 根文件系统重新挂载
	[ $? -eq 0 ] && success "Remount rootfs"  || failure "Mount others filesystem"
	
	mount -a  # 挂载etc/fstab中定义的文件系统
	[ $? -eq 0 ] && success "Mount others filesystem"  || failure "Mount others filesystem"
	
	echo "Set the hostname..."
	[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network  # .命令读取文件
	[ -z $HOSTNAME -o "$HOSTNAME"  == '(none)' ] && HOSTNAME=localhost
	/bin/hostname $HOSTNAME
	[ $? -eq 0 ] && success "Set the hostname" || failure "Set the hostname"
	
	# Initializing network device...
	echo "Initializing network device..."
	/sbin/insmod /lib/modules/mii.ko
	/sbin/insmod /lib/modules/pcnet32.ko
	[ $? -eq 0 ] && success "Initializing network device" || failure "Initializing network device"
	ifconfig lo 127.0.0.1/8
	[ $? -eq 0 ] && success "Activating loopback network device" || failure "Activating loopback network device"

设定内核参数

/etc/sysctl.conf  # 红帽7在/etc/sysctl.d99-sysctl.conf
sysctl -p

/root/bincp.sh
	sysctl

vim etc/sysctl.conf
	net.ipv4.ip_forward = 1

vim /etc/rc.d/rc.sysinit
	#添加如下一行:
	sysctl -p &>/dev/null
	[ $? -eq 0 ] && success "Set kernel parameter" || failure "Set kernel parameter"

登录时验证用户账号

PAM: Pluggable Authentication Module # 可插入式认证模块,该模块在/etc/pam.d/*
nsswitch: Network Service Switch 
	通过这个框架我们可以对登录login的认证做切换,比如:Linux使用/etc/passwd找用户,使用/etc/shadow找用户密码,用/etc/group找用户GID
	库:libnss_file.so,libnss_nis.so,libnsss_ldap.so
	配置文件:/etc/nsswitch.conf  # 根据依赖的库,在这个配置文件中配置,去指定的文件中找账号密码
		
cp -d /lib/libnss_files* /mnt/sysroot/lib/  # -d选项能将文件的链接也拷贝过去
cp -d /usr/lib/libnss_files.so /mnt/sysroot/usr/lib/
cp -d /usr/lib/libnss3.so /usr/lib/libnssckbi.so /usr/lib/libness
cp -d /usr/lib/libnss3.so /usr/lib/libnssckbi.so /usr/lib/libnssutil3.so /mnt/sysroot/lib/
sync
vim /mnt/sysroot/etc/nsswitch.conf
cp /etc/nsswitch.conf /mnt/sysroot/etc
# 保留以下4行
    passswd:	files
    shadow:		files
    group:		files

    # hosts:	db files nisplus nis dns
    hosts:		files dns

grep -E "^(root|hadoop)>" /etc/passwd > /mnt/sysroot/etc/passwd
grep -E "^(root|hadoop)>" /etc/shadow > /mnt/sysroot/etc/shadow
grep -E "^(root|hadoop)>" /etc/group > /mnt/sysroot/etc/group
sync

./bincp.sh
    mingetty
    useradd
    passwd
    userdel
    usermod
    groupadd

vim /etc/inittab
# 修改如下两行:
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2

# 下载登录的二进制文件
cd /bin
chmod +x login
ldd login
ls /lib
	libcrypt.so.1 => /lib/libcrypt.so.1
	libm.so.6 => /libm.so.6 (0x007bb000)
	libc.so.6 => /lib/libc.so.6 (0x00658000)
	/lib/ld-linux.so.2 (0x00639000)

chroot /mnt/sysroot/
login
小系统提示输入用户名和密码:

cd
vim .bash_profile
PS1='[u@h W]S'  # PS1 就是用来定义用户命令提示符信息的,u表示替换为用户名,h表示替换为主机名,W表示替换为工作目录的基名,w表示替换为工作目录的全名
export PS1		

开机密码忘记,进入单用户模式

umount /mnt/sysroot
mke2fs -j /dev/hda2
mount /dev/hda2 /mnt/sysroot/
cd /mnt/sysroot
zcat /root/sysroot.7.gz | cpio -id
chmod -R og=--- root/

vim root/.bash_profile
export PS1='[u@h W]$' # 表示root用户显示的是#,普通用户显示的是$.
# 提供单用户模式,要修改/etc/inittab,添加1级别
l1:1:wait:/etc/rc.d/rc 1

cd etc/
cd rc.d/
mkdir rc1.d
mkdir rc1.d
cd rc1.d/
ln -sv ../init.d/network K90network
ln -sv ../init.d/tserver K33tserver

vim /etc/init.d/single

#!/bin/bash
#
# chkconfig:
# description:
#
case $1 in
start)
  ;;
*)
  echo "Usage:single start."
  ;;
esac
exec /sbin/init S  # init 0 和init S 都表示切换到级别1
chmod +x rc.d/init.d/single
cd rc.d/rc1.d/
ln -sv ../init.d/single S98single
sync 
cd /mnt/sysroot
find  . | cpio -H newc --quiet -o | gzip > /root/sysroot.8.gz
cd
sync

开启小系统,进入单用户级别:
按 e 键进入grub,键入1,按b键进入引导;然后进入单用户登录模式;登录后修改密码:passwd;但是没有pam,密码和用户相关的几个文件即使移到/mntsysroot/etc也不能修改密码
当修改完密码后,init 3 进入多用户文本模式(正常使用的模式)


使用busybox制作便携的小系统

内核编译:
busybox
Kernel +ROOTFS
kernel+initrd(ramdisk)
kernel+
busybox-->initrd
kernel + initrd(busybox)-->rootfs(busybox)
kernel
RHEL5.8 + busybox(initrd) + rootfs(busybox)
查看本机硬件设备信息
cat /proc/cpuinfo
lsusb  # 查看usb设备的类型和接口信息
lspci # 查看pci总线上的所有设备
hal-device  # hal:hardware abstract layer 硬件抽象层,显示设备上的所有硬件信息


编译内核:
1.配置
make menuconfig
make gconfig
make kconfig
make oldconfig
make config

保存为.config
2.make 
make modiles_install
make install

模块安装位置:/lib/modules/KERNEL_VERSION/

如何实现部分编译:
1.只编译某子目录下的相关代码:
make dir/ 
make arch/
make drivers/net/  # 只编译与网卡相关的驱动
2.只编译部分模块
make M=drivers/net
3.只编译某一模块
make drivers/net/pcnet32.ko
4.将编译完成的结果放置于别的目录中
make O=/tmp/kernel

如何编译busybox:
	官网下载busybox.tar.bz2二进制包
	解压&&cd busybox
	make menuconfig
	勾选 [*] Build static binary (no shared libs) 
	exit
	
准备IDE磁盘:
/dev/hda1:ext3 # 格式化成ext3类型的 挂载到/boot  用于放内核和init、grub文件的
/dev/hda2:ext3 / # 关在到rootfs

cd busybox
make install # 报错
下载Linux内核
解压 && mv busybox /usr/bin
cd /usr/bin/busybox/include/uapi/mtd
cp ./ubi-user.h /root/busybox/include/uapi/mtd # mkdir -p /root/busybox/include/uapi/mtd
make install
在busybox内会生成_install目录及其下文件
cp _install /tmp/busybox/
cd /tmp/busybox
ls
rm linuxrc
mkdir proc sys etc dev lib/modules -pv
mkdir /mnt/sysroot
modinfo ext3
	mbcache,jbd2  # ext3模块所依赖的库
cp /lib/modules/3.10.0-1160.21.1.el7.x86_64/kernel/fs/ext4/ext4.ko.xz /tmp/busybox/lib/modules
	
modinfo mbcache
cp /lib/modules/3.10.0-1160.21.1.el7.x86_64/kernel/fs/mbcache.ko.xz /tmp/busybox/lib/modules
modinfo jbd2
cp /lib/modules/3.10.0-1160.21.1.el7.x86_64/kernel/fs/jbd2/jbd2.ko.xz /tmp/busybox/lib/modules

vim init  # 编写init脚本
    #!/bin/sh  # 没有bash
    #
    mount -t proc proc /proc
    mount -t sysfs sysfs /sys
    
    insmod /lib/modules/jbd.ko
    insmod /lib/modules/ext3.ko
    
    mdev -s
    
    mount -t ext3 /dev/hda2 /mnt/sysroot
    exec switch_root /mnt/sysroot /sbin/init
    
    echo -e "	Welcome to 33[34mChaoZhang 33[0m Linux"
    # linux有一个udev 可以扫描所有硬件设备,busybox在/sbin目录下也提供了一个mdev用汉语扫描硬件设备
    mdev -s
    mount -n -o remount,rw /dev/hda2 / # 挂载额外的文件系统
    mount -a  # 挂载fstab中定义的文件系统

mknod dev/console  c  5  1  # 当前在busybox目录中
mknod  dev/null  c  1  5

mkdir tmp
find . | cpio -H newc --quiet -o | gzip -9 > /mnt/boot/initrd.gz
# 准备内核
cp /boot/vmlinuz-2.6.18-308.el5 /mnt/boot/vmlinuz
# 安装grub
grub-install --root-directory=/mnt /dev/hda
ls /mnt/boot/
	grub initrd.gz vmlinuz
	
vim /mnt/boot/grub/grub.conf
    default=0
    timeout=3
    title ZhangChao Linux(2.6.18)
    root(hd0,0)
    kernel /vmlinuz ro root=/dev/hda2 
    initrd /initrd.gz

cp _initall/* /mnt/sysroot/ -a
cd /mnt/sysroot
rm linuxrc
mkdir proc sys dev tmp var/{log,lock,run} lib/modules etc/rc.d/init.d root boot mnt media -pv

vim etc/inittab
    ::sysinit:/etc/rc.d/rc.sysinit
    console::respawn:-/bin/sh
    ::ctrllaltdel:/sbin/reboot
    ::shutdown:/bin/umount -a -r

vim etc/fstab
    sysfs			/sys			sysfs	defaults		0  0
    proc			/proc			proc	defaults		0  0
    /dev/hda1		/boot             ext3	  defaults		  0  0
    /dev/hda2		/				ext3	defaults		1  1
sync
sync
mknod dev/console c 5 1
mknod dev/null c 1 3

vim etc/rc.d/rc.sysinit

    #!/bin/bash
    #
    echo -e " Welcome to 33[34m ChaoZhang 33m[0m Linux "
    echo -e "Remounting the root filesystem ......[ 33m[32mOK33[0m ]"
    mount -t proc proc /proc
    mount -t sysfs sysfs /sys
    mount -o remount,rw /

    echo -e "Creating the files of device .......33m[32mOK33[0m"
    mdev -s

    echo -e "Mounting the filesystem .........33m[32mOK33[0m"
    mount -a
    swapon -a

chmod +x etc/rc.d/rc.sysinit

练习

/sysroot下的busybox至另一个目录,以实现与真正的根文件系统分开制作,我们这里选择使用/mnt/temp目录;
mkdir -pv /tmp/busybox
cp -r /mnt/sysroot/* /tmp/busybox

四、制作initrd
cd /tmp/busybox
#1.建立rootfs:
mkdir -pv proc sys etc/init.d tmp dev mnt/sysroot
#2.创建两个必要的设备文件:
mknod dev/console  c  5  1
mknod  dev/null  c  1  5

#3.为initrd 制作init程序,此程序的主要任务是实现rootfs的切换,因此,可以以脚本的方式来实现它;

rm linuxrc
vim init
# 添加以下内容
#!/bin/bash
#
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mdev -s
mount -t ext3 /dev/hda2 /mnt/sysroot
exec switch_root /mnt/sysroot /sbin/init
# 给此脚本执行权限
chmod +x init

# 制作initrd
find . | cpio --quiet -H newc -o | gzip -9 -n > /mnt/boot/initrd.gz

# 五、建立真正的根文件胸痛
cd /mnt/sysroot
# 1.建立rootfs
mkdir -pv proc sys etc/rc.d/init.d tmp dev/pts boot var/log
# 2.创建两个必要的设别文件
mknod dev/console c  5  1
mknod  dev/null  c  1  3
#3.建立系统初始化脚本文件
vim etc/rc.d/rc.sysinit
# 添加如下内容:
#!/bin/bash
#
echo -e " Welcome to 33[31mToyLinux33m[0m "
echo -e "Remounting the root filesystem ......[ 33m[32mOK33[0m ]"
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -o remount,rw /

echo -e "Creating the files of device .......33m[32mOK33[0m"
mdev -s

echo -e "Mounting the filesystem .........33m[32mOK33[0m"
mount -a
swapon -a

echo -e "Starting the log daemon..............33m[32mOK33[0m"
syslogd
klogd

echo -e "Configuring loopback interface ......[ 33m[32mOK33[0m ]"
ifconfig lo  127.0.0.1/24
ifconfig eth0 172.16.100.9/16

# END

而后让此脚本具有执行权限
chmod +x etc/init.d/rc/sysinit
# 4.配置init及其所需要inittab文件
cd /mnt/sysroot
rm -f linuxrc

为init进提供配置文件:
vim etc/inittab

添加如下内容:
::sysinit:/etc/rc.d/rc.sysinit
console::respawn:-/bin/sh
::ctrllaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

# 5.为系统准备一个"文件系统表"配置文件/etc/fstab
vim etc/fstab

添加如下内容:
sysfs			/sys			sysfs	defaults		0  0
proc			/proc			proc	defaults		0  0
/dev/hda1		/boot             ext3	  defaults		  0  0
/dev/hda2		/				ext3	defaults		1  1

# 6. 由于在rc.sysinit文件中启动了日志进程,因此系统在运行中会产生大量日志并将其显示于控制台,这将会经常性的打断正在进行的工作,为了避免这种情况我们这里为日志进程建立配置为你教案,为其指定将日志发送至/var/log/messages文件;
vim etc/syslog.conf

添加如下一行:
*.conf		/var/log/messages

六、好了,至此一个简易的基于内存运行的小系统已经构建出来了,我们接下来为此系统创建所需的引导程序

grub-install --root-directory=/mnt  /dev/hda

说明:此处的/dev/hda为目标系统所在的那块新磁盘;

接下来为grub建立配置文件:
vim /mnt/boot/grub/grub.conf

添加类似如下内容:

vim /mnt/boot/grub/grub.conf
    default=0
    timeout=3
    color	ligth-green/black light-magenta/black
    title ZhangChao Linux(2.6.18)
    root(hd0,0)
    kernel /vmlinuz ro root=/dev/hda2 quiet
    initrd /initrd.gz

接下来将此块硬盘接入一个新的主机(这里使用的是虚拟机),启动一下并测试使用。

七、为新构建的ToyLinux启用虚拟控制台

这个可以通过宿主机来实现,也可以直接启动刚构建成功的小Linux进行配置,我们这里采用通过宿主机的方式(重新启动宿主机)
cd /mnt/sysroot
将etc/inittab文件改为如下内容:
::sysinit:/etc/init.d/rc.sysinit
tty1::askfirst:/bin/sh
tty2::askfirst:/bin/sh
tty3::askfirst:/bin/sh
tty4::askfirst:/bin/sh
tty5::askfirst:/bin/sh
tty6::askfirst:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
好了,接下来就可以测试六个虚拟控制台的使用了。

八、尽管上述第七步已经实现了虚拟控制台,但其仍是直接进入系统,且系统没有用户账号等安全设施,这将不利于系统的安全性。因此,接下来的这步实现为系统添加用户账号(这里仍然基于宿主机实现)。
1.为了目标主机建立passwd账号文件
cd /mnt/sysroot
vim etc/passwd

添加如下内容:
root:x:0:0::/root:/bin/sh
而后为root用户创建"家"目录:
mkdir root

2.为目标主机创建group账号文件
vim etc/group

添加如下内容:
root:x:0:

3.为目标主机建立shadow影子口令文件,这里采用直接复制宿主机的shadow文件中关于root口令行的行来实现
grep "^root" /etc/shadow > etc/shadow

注:等目标主机启动时,root用户的口令也是宿主机的root用户的口令,您可以在目标主机启动以后再动手更改root用户的口令。

4.将 etc/inittab 文件改为如下内容:
::sysinit:/etc/init.d/rc.sysinit
::respawn:/sbin/getty 9600 tty1
::respawn:/sbin/getty 9600 tty2
::respawn:/sbin/getty 9600 tty3
::respawn:/sbin/getty 9600 tty4
::respawn:/sbin/getty 9600 tty5
::respawn:/sbin/getty 9600 tty6
::shutdown:/bin/umount -a -r
::ctrlaltdel:/sbin/reboot
好了,接下来就可以重新启动目标主机进行验证了。

九、在系统登录时提供banner信息
这个可以通过宿主机来实现,也可以直接在目标主机上进行配置,这里采用直接在目标主机上配置的方式:

vi /etc/issue
添加如下内容:
Welcome to ChaoZhang Linux(http://www.chanzhang.com)...
Kernel 
原文地址:https://www.cnblogs.com/zhangchaocoming/p/14792181.html