LinuxOS的启动流程
因6和7俩个系列的启动流程有区别,所以我把他们分开来写
linux可看作是内核和根文件系统组成我们把内核单独拿出来总结一下
一、CentOS6系列启动流程
首先总结一下总体的流程,接下来展开来叙述:POST加电自检 -- MBR(0扇区前446个字节为GRUB第1阶段) -- (在1扇区后存放GRUB第1.5阶段)GRUB(第2阶段)-- 加载内核(vmlinuz,initramfs)-- 启动第一个进程(init ;/etc/ini/*.conf init 程序的配置文件)-- 读取/etc/inittab文件来决定进入的系统级别 -- 执行/etc/rc.d/rc.sysinit脚本来初始化系统 -- 使用/etc/rc.d/rc脚本来根据当前所在的系统级别来读取对应/etc/rc#.d/下的脚本 -- K开头的脚本不启动,S开头的脚本启动,启动顺序按后边跟的数子大小来决定 -- 最后执行的脚本/etc/rc.d/rc.local -- 启动/bin/login进程来启动登录程序 --- OK!
- 加载BIOS的硬件信息,获取第一个启动设备
- 读取第一个启动设备MBR的引导加载程序(grub)的启动信息
- 加载核心操作系统的核心信息,核心开始解压缩,并尝试驱动所有的硬件设备
- 核心执行init程序,并获取默认的运行信息
- init程序执行/etc/rc.d/rc.sysinit文件
- 启动核心的外挂模块
- init执行运行的各个批处理文件(scripts)
- init执行/etc/rc.d/rc.local
- 执行/bin/login程序,等待用户登录
- 登录之后开始以Shell控制主机
1、POST
Power-On-Self-Test:加电自检,是BIOS功能的一个主要部分。负责完成对CPU、主板、内存、硬盘子系统、显示子系统等硬件情况的检测。
BIOS:Basic Input and Output System,保存着有关计算机系统最重要的基本输入输出程序,系统信息设置、开机加电自检程序和系统启动自举程序等。
CMOS:保存主板的设置时间等参数,依靠主板上的CMOS纽扣电池。
2、BootLoader
引导加载器,Windows使用的bootLoader是ntloader,只可以引导Windows系统;Linux使用的bootloader早期有LILO(LInux LOader),现在6系列用的GRUB0.97版,7系列使用的是GRUB2。
3、GRUB
grub总共分为三个阶段:
- 第1阶段:存放在mbr前446个字节
- 第1.5阶段:1.5阶段存放在1-27扇区;由于grub1阶段需要去读取grub2阶段的程序和配置文件,但是grub2阶段的程序存放在磁盘的/boot分区中,想要读取分区中的文件就必须要有驱动文件系统的驱动模块,1.5阶段就是来做这件事的。
- 第2阶段:存放在磁盘可的/boot分区上(/boot/grub/),启动时选择内核版本界面,还有配置文件都是由第2阶段负责。
功用:
- 提供启动菜单、并提供交互式接口
- 加载用户选择的内核或操作系统
- 为菜单提供了保护机制
grub的配置文件(/boot/grub/grub.cfg)
default=0 #默认title timeout=5 #grub菜单选择超时时间 splashimage=(hd0,0)/grub/splash.xpm.gz #grub菜单背景图片 hiddenmenu #隐藏grub选择菜单 password --md5 | ----encrypted 口令 #加密方式和口令,为grub加密防止进如单用户模式修改密码,口令使用下面的命令生成
# grub-md5-crypt 生成MD5的密码 # grub-crypt 生成sha12的密码
title Red Hat Enterprise Linux 6 (2.6.32-642.el6.x86_64) root (hd0,0) #指定的是/boot所在磁盘的分区"hd0,0"表示第一块磁盘的第一个分区 kernel /vmlinuz-2.6.32-642.el6.x86_64 ro root=UUID=e1d36be7-5027-4847-9d80-135ac9fb798e rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet #向内核传递的cmdline参数 initrd /initramfs-2.6.32-642.el6.x86_64.img #指定initramfs文件的所在路径,注意:(这里的"/"相对的是/boot分区)
如果grub损坏我们可以用下面命令修复
grub-install --root-directory=DIR /dev/DISK --root-directory=DIR:根目录
如果grub配置丢失了怎么办:
在开机的时候会进入grub的命令行接口,但是无法找到内核和ramdisk,所以我们手动指定参数和路径就可以启动系统了。
help: 获取帮助列表 help KEYWORD: 详细帮助信息 find (hd#,#)/PATH/TO/SOMEFILE: root (hd#,#) kernel /PATH/TO/KERNEL_FILE: 设定本次启动时用到的内核文件;额外还可添加许多内核支持使用的cmdline参数 initrd /PATH/TO/INITRAMFS_FILE: 设定为选定的内核提供额外文件的ramdisk boot: 引导启动选定的内核
分别指定root(指的是/boot分区),kernel指定内核,initrd指定ramdisk文件,然后boot就可以启动系统了,进入系统后重新编辑/boot/grub.cfg文件来修复问题
4、kernel自身初始化
- 探测可识别到的所有硬件设备
- 加载硬件驱动程序(借助于ramdisk加载驱动)
- 以只读方式挂载根文件系统
- 运行用户空间的第一个应用程序:/sbin/init
5、ramdisk
在grub第2阶段的时候只能识别到/boot分区,这个时候内核开始初始化,探测完硬件后开始需要去找根,但是这时还没有驱动程序,所以这个时候需要借助ramdisk来驱动硬件。在CentOS5系列中文件名为/boot/inird,6和7已经改成initramfs。
initramfs中也提供了一个根文件系统,其中包括了硬件必须的驱动,到了这步内核借助这个虚根文件系统来挂载真正的根文件系统。
initramfs文件是在安装系统时按当前的环境来生成的。
如果这个文件损坏了我们也可以使用工具来修复:
# mkinitrd /boot/initramfs-`uname -r`.img `uname -r` 为当前正在使用的内核重新制作ramdisk文件
6、init初始化
init程序启动系统的第一个进程init,它负责创建系统启动后的所有服务进程
init程序的类型:
- CentOS5.x:SysV
- CentOS6.x:Upstart
- CentOS7.x:Systemd
初始化的相关文件:
- /etc/inittab:定义系统默认的启动级别
id:3:initdefault:
- /etc/init/control-alt-delete.conf:设定按Ctrl + Alt + Del 是否会重启
start on control-alt-delete exec /sbin/shutdown -r now "Control-Alt-Delete pressed"
- /etc/init/tty.conf
- /etc/init/start-ttys.conf
- /etc/init/rc.conf
- /etc/init/prefdm.conf
7、系统级别(CentOS6.x)
- 0:关机
- 1:单用户模式(root自动登录), single, 维护模式
- 2: 多用户模式,启动网络功能,但不会启动NFS;维护模式
- 3:多用户模式,正常模式;文本界面
- 4:预留级别;可同3级别
- 5:多用户模式,正常模式;图形界面
- 6:重启
init #:切换至#级别
runlevel:查看当前的运行级别和上一运行级别
示例:进入单用户模式
1)在启动过程中看到Booting 。。。的倒计时字样按下esc键
2)按a键修改启动参数,在quiet后加1(单用户模式)
3)按回车键启动,进入单用户模式,可以直接修改root的密码,或者可以修改一些其他服务配置文件错误导致的系统无法进入正常模式的操作。
8、系统初始化脚本(/etc/rc.d/rc.sysinit)
- 设置主机名
- 设置欢迎信息
- 激活udev和selinux
- 挂载/etc/fstab文件中定义的文件系统
- 检测根文件系统,并以读写方式重新挂载根文件系统
- 设置系统时钟
- 激活swap设备
- 根据/etc/sysctl.conf文件设置内核参数
- 激活lvm及software raid设备
- 加载额外设备的驱动程序
- 清理操作
9、启动服务脚本(/etc/rc.d/rc)
由/etc/rc.d/rc脚本控制服务脚本启动还是非启动
for i in /etc/rc$runlevel.d/S* ; do # Check if the subsystem is already up. subsys=${i#/etc/rc$runlevel.d/S??} [ -f /var/lock/subsys/$subsys ] && continue [ -f /var/lock/subsys/$subsys.init ] && continue check_runlevel "$i" || continue # If we're in confirmation mode, get user confirmation if [ "$do_confirm" = "yes" ]; then confirm $subsys rc=$? if [ "$rc" = "1" ]; then continue elif [ "$rc" = "2" ]; then do_confirm="no" fi fi update_boot_stage "$subsys" # Bring the subsystem up. [ -n "$UPSTART" ] && initctl emit --quiet starting JOB=$subsys if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then export LC_ALL=C exec $i start fi $i start [ -n "$UPSTART" ] && initctl emit --quiet started JOB=$subsys done
rc脚本读取/etc/rc.d/rc#.d/下的所有脚本,以K开头的服务脚本不启动,以S开头的服务脚本启动。
- K*: K##*:##运行次序;数字越小,越先运行;数字越小的服务,通常为依赖到别的服务
- S*: S##*:##运行次序;数字越小,越先运行;数字越小的服务,通常为被依赖到的服务
/etc/rc.d/rc#.d/下的所有脚本都是/etc/rc.d/init.d/下的脚本的符号连接,链接名由chkconfig管理。
/etc/rc.d/rc.local:在所有启动脚本执行完成后执行此脚本,可以把不便或不需写为服务脚本放置于/etc/rc.d/init.d/目录,且又想开机时自动运行的命令,可直接放置于/etc/rc.d/rc.local文件中。
所有服务启动完成后启动登录程序(/bin/login)。
CentOS 6 init程序为: upstart, 其配置文件:/etc/inittab, /etc/init/*.conf,配置文件的语法 遵循 upstart配置文件语法格式,和CentOS5不同。
服务管理工具(CentOS6.x)
chkconfig
- --list 查看
- --level ##:指定级别,默认为2 3 4 5
- --add 将脚本加入对应的级别(需要将脚本放到/etc/rc.d/init.d/目录下,并且在脚本开头加上chkconfig: 启动级别 关闭优先级 开启优先级),一般“关闭优先级 + 开启优先级 = 100”
- --del 删除对应级别脚本
service 服务名 { start | stop | restart }
- --status-all 查看所有服务的状态
ntsysv:字符界面工具,用来设置开启自启的服务
二、CentOS7系列启动流程
CentOS7与6版本的不同之处:
- 6 : grub0.9和upstart
- 7 : grub2和systemd
主要介绍一下grub2和systemd吧,其他的启动流程几乎一样
grub2
1、/etc/default/grub :grub配置文件模板
GRUB_TIMEOUT=5 #grub菜单选项超时时间 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved #grub菜单默认选择的title GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="rhgb quiet" #向内核传递的cmdline参数 GRUB_DISABLE_RECOVERY="true"
2、/boot/grub2/grub.cfg :grub配置文件,建议使用以下命令生成
# grub2-mkconfig -o /boot/grub2/grub.cfg
3、在救援模式下修复grub2
# chroot /mnt/sysimage # grub2-install /dev/sda # grub2-mkconfig -o /boot/grub2/grub.cfg
4、在grub命令行启动系统(grub2配置文件损坏的情况下)
> insmod xfs > set root=(hd0,1) > linux16 /vmlinux-... root=/dev/sda2 selinux=0 > initrd16 /initramfs-...
systemd
系统启动和服务器守护进程管理器,负责在系统启动或运行时,激活系统资源,服务器进程和其它进程。
Systemd新特性:
- 系统引导时实现服务并行启动
- 按需启动守护进程
- 自动化的服务依赖关系管理
- 同时采用socket式与D-Bus总线式激活服务
- 系统状态快照
unit
表示不同类型的systemd对象
/usr/lib/systemd/system:每个服务最主要的启动脚本设置,类似于6系列的/etc/init.d/目录的功能
/run/systemd/system:系统执行过程中所产生的服务脚本
/etc/systemd/system:管理员建立的执行脚本,功能类似于6系列中/etc/rc.d/rcN.d/Sxx目录的功能
类型:
- Service unit: (.service),用于定义系统服务
- Target unit: (.target),用于模拟实现运行级别
- Device unit: (.device),用于定义内核识别的设备
- Mount unit: (.mount),定义文件系统挂载点
- Socket unit: (.socket), 用于标识进程间通信用的socket文件,也可在系统启动时,延迟启动服务,实现按需启动
- Snapshot unit: (.snapshot),管理系统快照
- Swap unit: (.swap), 用于标识swap设备
- Automount unit:(.automount),文件系统的自动挂载点
- Path unit:(.path),用于定义文件系统中的一个文件或目录使用,常用于当文件系统变化时,延迟激活服务
service unit文件格式
[Unit] #定义与Unit类型无关的通用选项 Description=The Apache HTTP Server #描述信息 After=network.target remote-fs.target nss-lookup.target #依赖服务,定义unit的启动次序,表示当前unit应该晚于哪些unit启动,其功能与Before相反 Documentation=man:httpd(8) Documentation=man:apachectl(8) #Requires:依赖到的其它units,强依赖,被依赖的units无法激活时,当前unit也无法激活 #Wants:依赖到的其它units,弱依赖 #Conflicts:定义units间的冲突关系 [Service] #与特定类型相关的专用选项;此处为Service类型 Type=notify #定义影响ExecStart及相关参数的功能的unit进程启动类型 EnvironmentFile=/etc/sysconfig/httpd #环境配置文件 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND #指明启动unit要运行命令或脚本的绝对路径 ExecReload=/usr/sbin/httpd $OPTIONS -k graceful #指明重载unit要运行命令或脚本的绝对路径 ExecStop=/bin/kill -WINCH ${MAINPID} #指明停止unit要运行的命令或脚本 KillSignal=SIGCONT PrivateTmp=true #simple:默认值,这个daemon主要由ExecStart接的指令串来启动,启动后常驻于内存中 #forking:由ExecStart启动的程序透过spawns延伸出其他子程序来作为此daemon的主要服务。原生父程序在启动结束后就会终止 #oneshot:与simple类似,不过这个程序在工作完毕后就结束了,不会常驻在内存中 #dbus:与simple类似,但这个daemon必须要在取得一个D-Bus的名称后,才会继续运作.因此通常也要同时设定BusNname= 才行 #notify:在启动完成后会发送一个通知消息。还需要配合 NotifyAccess 来让 Systemd 接收消息 #idle:与simple类似,要执行这个daemon必须要所有的工作都顺利执行完毕后才会执行。这类的daemon通常是开机到最后才执行即可的服务 [Install] #定义由“systemctl enable”以及"systemctl disable“命令在实现服务启用或禁用时用到的一些选项 WantedBy=multi-user.target #被哪些units所依赖,弱依赖 #Alias:别名,可使用systemctl command Alias.service #RequiredBy:被哪些units所依赖,强依赖 #Also:安装本服务的时候还要安装别的相关服务
新创建unit文件后或者修改了unit文件需要使用以下命令来重载
# systemctl daemon-reload
systemctl
用法:systemctl 子命令 name.service
子命令:
start | stop | restart |status | reload :启动 | 停止 | 重启 | 状态 | 重读配置文件
enable :设置开机自动启动
disable :设置开机不自动启动
try-restart:服务在启动状态才会执行重启,服务在停止状态不会重启
reload-or-restart :重新加载配置文件再启动服务
reload-or-try-restart :重载或服务在启动状态才会执行重启
mask:禁止服务启动
unmask:取消禁止服务启动
is-active:查看服务是否在激活状态
is-enabled :查看指定服务是否开机自启
list-dependencies :查看服务的依赖关系
kill :杀掉指定服务的进程
查看类子命令:
list-units :显示所有单元(unit)的状态
- -t service :查看指定的类型(服务)
- -a :查看所有的服务
list-unit-files -t service -a:查看所有服务的开机自启状态
- loaded:Unit配置文件已处理
- active(running):一次或多次持续处理的运行
- active(exited):成功完成一次性的配置
- active(waiting):运行中,等待一个事件
- inactive:不运行
- enabled:开机启动
- disabled:开机不启动
- static:开机不启动,但可被另一个启用的服务激活
--failed -t service:查看启动失败的服务
查看指定服务在哪些运行级别下启用和禁用
ls /etc/systemd/system/*.wants/name.service
运行级别
poweroff.target ==> 0 rescue.target ==> 1 multi-user.target ==> 2,3,4 graphical.target ==> 5 reboot.target ==> 6
切换运行级别:
# systemctl isolate multi-user.target
如果需要在启动中进入rescue模式,需要在linux16后加以下cmdline命令
systemd.unit=rescue.target
破解root口令
方法一: 在grub菜单按e进入编辑模式 在linux16后加rd.break Ctrl + x启动 # mount -o rw,remount /sysroot # chroot /sysroot # passwd # touch /.autorelabel 防止selinux打标签失败 # exit # reboot
方法二: 在linux16后加init=/sysroot/bin/sh # chroot /sysroot # passwd touch /.autorelabel
systemctl
相关子命令:
get-default :查看当前默认启动模式
set-default :设置默认启动模式
rescue :切换紧急救援模式
emergency:切换至emergency模式,比救援模式更底层一级
halt | poweroff :关机
reboot :重启
suspend :挂起
hibernate :休眠
hybrid-sleep :休眠并挂起
CentOS7系列启动流程总结:
- UEFi或BIOS初始化,运行POST开机自检
- 选择启动设备
- 引导装载程序:grub2
- 加载装载程序的配置文件:/boot/grub2/grub.cfg
- 加载initramfs驱动模块:/boot/initramfs-3.10.0-693.el7.x86_64.img
- 加载内核:/boot/vmlinuz-3.10.0-693.el7.x86_64
- 内核初始化:systemd
- 执行initrd.target所有单元,包括挂载/etc/fstab
- 从initramfs根文件系统切换到磁盘根目录
- systemd执行默认target配置,配置文件/etc/systemd/system/default.target
- systemd执行sysinit.target初始化系统及basic.target准备操作系统
- systemd启动multi-user.target下的本机与服务器服务
- systemd执行multi-user.target下的/etc/rc.d/rc.local
- Systemd执行multi-user.target下的getty.target及登录服务
- 如果启动图形界面systemd执行graphical需要的服务
三、内核(kernel)
kernel职责:
进程管理、内存管理、网络管理、驱动程序、文件系统、安全功能
内核的设计流派分为单内核和微内核:linux内核为单内核流派,把所有的功能都集成于同一个程序;Windows,Solaris系统的内核是微内核设计,每种功能都使用一个单独的子系统来实现,在一个中心框架下协同工作,从理论上来说微内核的设计更为先进。
linux内核的特点:
- 模块化:如把文件系统、硬件启动等编译成模块,使用时装载,
- 支持内核模块的动态装载和卸载,更灵活
linux的内核组成:
- /boot/vmlinz-VERSION-release:核心文件
- ramdisk
- /boot/initrd-VERSION-release.img(5.x)
- /boot/initramfs-VERSION-release.img(6.x和7.x)
- /lib/modules/VERSION-release :存放模块文件目录
查看内核当前运行的cmdline参数:
[root@rhel6 ~]# cat /proc/cmdline ro root=UUID=e1d36be7-5027-4847-9d80-135ac9fb798e rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
内核参数文档:/usr/share/doc/kernel-doc-2.6.32/Documentation/kernel-parameters.txt,需要安装以下包。
yum install kernel-doc-2.6.32-696.el6.noarch
简单的内核编译流程:(环境:CentOS7.4mini版)
1、准备:
(1) 准备好开发环境(yum groupinstall -y "Development Tools" ; yum install -y ncurses-devel elfutils-libelf-devel openssl-devel bc)
(2) 获取目标主机上硬件设备的相关信息
(3) 获取目标主机系统功能的相关信息
(4) 获取内核源代码包(www.kernel.org)
2、解压内核包,进入linux-xxx目录;调试配置文件(.config)
(a) make config:基于命令行以遍历的方式去配置内核中可配置的每个选项
(b) make menuconfig:基于curses的文本窗口界面
(c) make gconfig:基于GTK (GNOME)环境窗口界面
(d) make xconfig:基于QT(KDE)环境的窗口界面,支持“全新配置”模式进行配置
(a) make defconfig:基于内核为目标平台提供的“默认”配置进行配置
(b) make allyesconfig: 所有选项均回答为“yes“
(c) make allnoconfig: 所有选项均回答为“no“
3、编译
make -j #:全编译,如果我们只需要编译单个模块,那么我们可以cd到子目录或者make /path/MODULS.ko可以实现只对单个模块进行编译
-j:支持并行编译,#为物理CPU核心数
4、安装模块
make modules_install
5、安装内核文件,生成initramfs文件并且自动配置grub菜单
make install
6、reboot启动选择新内核进入系统就完成了
7、如果编译失败需要重新编译我们可以使用以下命令来清理
# make clean:清理大多数编译生成的文件,但会保留config文件等 # make mrproper: 清理所有编译生成的文件、config及某些备份文件 # make distclean:mrproper、patches以及编辑器备份文件
8、如果新的内核有bug需要卸载内核
- 删除/lib/modules/目录下不需要的内核库文件
- 删除/usr/src/linux/目录下不需要的内核源码
- 删除/boot目录下启动的内核和内核映像文件
- 更改grub的配置文件,删除不需要的内核启动列表
/proc:
内核把自己内部状态信息及统计信息,以及可配置参数通过proc伪文件系统加以输出
常见重要参数
/proc/sys/net/ipv4/icmp_echo_ignore_all /proc/sys/net/ipv4/ip_forward /proc/sys/net/ipv4/ip_default_ttl /proc/sys/vm/drop_caches /proc/sys/net/ipv4/tcp_syn_retries /proc/sys/net/ipv4/tcp_fin_timeout /proc/sys/net/ipv4/tcp_syncookies /proc/sys/net/ipv4/tcp_max_tw_buckets /proc/sys/net/ipv4/tcp_max_syn_backlog /proc/sys/net/ipv4/ip_local_port_range
/sys
sysfs:为用户使用的伪文件系统,输出内核识别出的各硬件设备的相关属性信息,也有内核对硬件特性的设定信息;有些参数是可以修改的,用于调整硬件工作特性。
相关管理工具:
sysctl:修改内核参数的工具
- -p 重新读入/etc/sysctl.conf
- -a 列出当前生效的内核参数
- -w net.ipv4.ip_forward = 1 即时生效
uname
- -r:显示内核版本号
- -a:显示全部信息
- -n:显示主机名
lsmod:显示已经装载的模块
modinfo:显示模块的详细信息
- -n:显示模块路径
- -p:显示模块参数
- -a:显示模块作者
- -d:显示模块描述信息
- -l:显示模块的遵循的协议
modprobe:装载模块
- -r:卸载模块
depmod:内核模块依赖关系文件及系统信息映射文件的生成工具
insmod:指定装载模块文件,但不自动解决依赖模块
rmmod:卸载模块
time cmd 检测命令执行花的时间
lscpu:查看CPU信息
lspci:查看pci相关信息
lsusb:查看usb相关信息
lsblk:查看块设备相关信息
hal-device:查看所有硬件信息(CentOS6.x)
四、制作一个mini_linux(环境:CentOS6.9)
为了对linux系统有更多的认识,我们可以基于CentOS的环境自己来在新硬盘上安装一个mini版的linux,只需要提供最基础的程序来运行。
1)准备工作
- VMware12虚拟机
- CentOS6.9系统
- 为系统加一块虚拟硬盘,20G,如果是在虚拟机开机加的硬盘需要扫描一下硬盘:# echo '- - -' > /sys/class/scsi_host/host2/scan
- 一个脚本,方便我们cp命令
#/bin/bash green_OK() { echo -e "[ \033[1;32mOK\033[0m ]"; } red_FAILED() { echo -e "[ \033[1;31mFAILED\033[0m ]"; } Screen=`stty -F /dev/tty size` Columus=${Screen#* } Spa_Col=$[Columus-16] success() { local i string="$1" Rt_Spa=$[$Spa_Col-${#string}] echo -n "$string" for i in `seq $Rt_Spa` ;do echo -n "." sleep 0.005 done green_OK } failed() { local i string="$1" Rt_Spa=$[$Spa_Col-${#string}] echo -n "$string" for i in `seq $Rt_Spa` ;do echo -n " " done red_FAILED } Ddir="/mnt/sysroot" [ ! -d "$Ddir" ] && mkdir "$Ddir" cpbin() { cmddir=`echo "$Cmd_path" |grep -o ".*/\b"` [ ! -d "${Ddir}${cmddir}" ] && mkdir -p "${Ddir}${cmddir}" cp -n "$Cmd_path" "${Ddir}${cmddir}" } libcp() { echo "$Lib_path" |while read line ;do libdir=`echo "$line" |grep -o ".*/\b"` [ ! -d "${Ddir}${libdir}" ] && mkdir -p "${Ddir}${libdir}" cp -n "$line" "${Ddir}${libdir}" 2>/dev/null done } while read -p "Input a cmd. (quit): " CMD ;do if [ "$CMD" == 'quit' ] ;then echo "Think you! Bye bye."; break; fi if ! which "$CMD" &>/dev/null ;then echo "not find $CMD or is a shell builtin, please input again!" failed "copy $CMD failed." continue fi Cmd_path=`which $CMD |grep -o "/.*"` Lib_path=`ldd $Cmd_path |sed -nr 's#.*[[:space:]]+(/.*) .*#\1#p'` cpbin libcp success "copy $CMD Complete." done
2)分区格式化新硬盘并且挂载
- sdb1分200M作为boot分区
- sdb2分10G作为根分区
- 剩下的可以自由分配
[root@rhel6 ~]# mkfs.ext4 /dev/sdb1 [root@rhel6 ~]# mkfs.ext4 /dev/sdb2 [root@rhel6 ~]# mkdir /mnt/sysroot # [root@rhel6 ~]# mount /dev/sdb2 /mnt/sysroot/ [root@rhel6 ~]# mkdir /mnt/sysroot/boot [root@rhel6 ~]# mount /dev/sdb1 /mnt/sysroot/boot
3)安装grub,提供内核和ramdisk文件,并且编辑配置文件
[root@rhel6 ~]# grub-install --root-directory=/mnt/sysroot/ /dev/sdb [root@rhel6 ~]# cp /boot/initramfs-2.6.32-642.el6.x86_64.img /mnt/sysroot/boot/initramfs.img [root@rhel6 ~]# cp /boot/vmlinuz-2.6.32-642.el6.x86_64 /mnt/sysroot/boot/vmlinuz [root@rhel6 ~]# cat >/mnt/sysroot/boot/grub/grub.conf <<EOF default=0 timeout=3 title mini_linux root(hd0,0) kernel /vmlinuz ro root=UUID=ce79412f-72b8-4313-8a55-5fb734ffacfe selinux=0 init=/bin/bash #这里是/dev/sdb2(mini_linux的根)的UUID
initrd /initramfs.img
4)接下来我们就可以把常用的cmd和对应依赖的库文件复制到我们的/mnt/sysroot/下了
[root@rhel6 ~]# mkdir -pv /mnt/sysroot/{bin,dev,etc,home,lib,lib64,media,mnt,opt,proc,root,sbin,sys,usr/{bin,etc,include,lib,lib64,libexec,local,sbin,share,src,tmp},var,tmp} [root@rhel6 ~]# ./copycmd.sh Input a cmd. (quit): bash copy bash Complete................................................................[ OK ] Input a cmd. (quit): ifconfig copy ifconfig Complete............................................................[ OK ] Input a cmd. (quit): insmod copy insmod Complete..............................................................[ OK ] Input a cmd. (quit): ping copy ping Complete................................................................[ OK ] Input a cmd. (quit): mount copy mount Complete...............................................................[ OK ] Input a cmd. (quit): ls copy ls Complete..................................................................[ OK ] Input a cmd. (quit): cat copy cat Complete.................................................................[ OK ] Input a cmd. (quit): df copy df Complete..................................................................[ OK ] Input a cmd. (quit): lsblk copy lsblk Complete...............................................................[ OK ] Input a cmd. (quit): blkid copy blkid Complete...............................................................[ OK ] Input a cmd. (quit): vi copy vi Complete..................................................................[ OK ] Input a cmd. (quit): sed copy sed Complete.................................................................[ OK ] Input a cmd. (quit): grep copy grep Complete................................................................[ OK ] Input a cmd. (quit): awk copy awk Complete.................................................................[ OK ] Input a cmd. (quit): quit Think you! Bye bye.
5)接下来我们去提供网卡驱动模块
[root@rhel6 ~]# mkdir /mnt/sysroot/lib/modules [root@rhel6 ~]# cp /lib/modules/2.6.32-642.el6.x86_64/kernel/drivers/net/e1000/e1000.ko /mnt/sysroot/lib/modules
6)现在一切都完成了,我们接下来关闭虚拟机,在关闭前执行几次sync命令来保证数据同步到磁盘上,然后将我们的mini_linux虚拟磁盘挂到新虚拟机上,调BIOS让其成为第一启动项,启动后将e1000.ko模块装载后就可以使用网络了
insmod /lib/modules/e1000.ko ifconfig eth0 192.168.222.222 up
个人学习笔记 2018.5.14 18:19