1、Linux 系统启动的基本过程和步骤:最近在某个版块看到有人讨论 GRUB 的问题,这里是我个人的一些理解。我想大部分还是正确的,但肯定也有理解错误的地方,在这里抛砖引玉了!Linux 系统启动过程大致按照如下步骤进行(这是一个简述):第一阶段:BIOS 启动引导阶段;在该过程中实现硬件的初始化以及查找启动介质;从 MBR 中装载启动引导管理器( GRUB)并运行该启动引导管理第二阶段:GRUB 启动引导阶段;装载 stage1装载 stage1.5装载 stage2读取/boot/grub.conf 文件并显示启动菜单;装载所选的 kernel 和 initrd 文件到内存中第三阶段:内核阶
2、段:运行内核启动参数;解压 initrd 文件并挂载 initd 文件系统,装载必须的驱动;挂载根文件系统第四阶段:Sys V init 初始化阶段:启动/sbin/init 程序;运行 rc.sysinit 脚本,设置系统环境,启动 swap 分区,检查和挂载文件系统;读取/etc/inittab 文件,运行在 /et/rc.d/rc.d 中定义的不同运行级别的服务初始化脚本;打开字符终端 1-6 号控制台/打开图形显示管理的 7 号控制台同时在上述过程中各阶段所需要读取的文件和操作的对象:BIOS 启动引导阶段 GRUB 启动引导阶段 内核阶段 /init/sysinit 阶段=None
3、/boot/grub/grub.conf /boot/vmlinuz- /etc/rc.d/rc.sysinit/boot/grub/stage1_5 /boot/initrd- /etc/inittab/boot/grub/stage2 /etc/rc.d/rc.d/etc/rc.d/init.d/*(下面是详细的过程) 第一阶段:系统上电开机后,主板 BIOS(Basic Input / Output System)运行 POST(Power on self test)代码,检测系统外围关键设备(如:CPU 、内存、显卡、 I/O、键盘鼠标等) 。硬件配置信息及一些用户配置参数存储在主板的
4、 CMOS( Complementary Metal Oxide Semiconductor)上(一般 64 字节) ,实际上就是主板上一块可读写的 RAM 芯片,由主板上的电池供电,系统掉电后,信息不会丢失。执行 POST 代码对系统外围关键设备检测通过后,系统启动自举程序, 根据我们在 BIOS中设置的启动顺序搜索启动驱动器(比如的硬盘、光驱、网络服务器等) 。选择合适的启动器,比如通常情况下的硬盘设备,BIOS 会读取硬盘设备的第一个扇区(MBR ,512 字节) ,并执行其中的代码。实际上这里 BIOS 并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容、并执行,BIOS
5、 的任务就完成了。此后将系统启动的控制权移交到MBR 部分的代码。注: 在我们的现行系统中,大多关键设备都是连在主板上的。因此主板 BIOS 提供了一个操作系统(软件)和系统外围关键设备(硬件)最底级别的接口,在这个阶段,检测系统外围关键设备是否“准备好” ,以供操作系统使用。第二阶段:BIOS 通过下面两种方法之一来传递引导记录:第一, 将控制权传递给 initial program loader(IPL) ,该程序安装在磁盘主引导记录(MBR )中第二, 将控制权传递给 initial program loader(IPL) ,该程序安装在磁盘分区的启动引导扇区中无论上面的哪种情况中,IP
6、L 都是 MBR 的一部分并应该存储于一个不大于 446 字节的磁盘空间中,因为 MBR 是一个不大于 512 字节的空间。因此 IPL 仅仅是 GRUB 的第一个部分(stage1) ,他的作用就是定位和装载 GRUB 的第二个部分(stage2) ;stage2 对启动系统起关键作用,该部分提供了 GRUB 启动菜单和交互式的 GRUB 的 shell。启动菜单在启动时候通过 /boot/grub/grub.conf 文件所定义的内容生成。在启动菜单中选择了 kernel 之后,GRUB 会负责解压和装载 kernel image 并且将 initrd 装载到内存中。最后 GRUB 初始化
7、 kernel 启动代码。完成之后后续的引导权被移交给 kernel。假设 Boot Loader 为 grub (grub-0.97),其引导系统的过程如下:grub 分为 stage1 (stage1_5) 和 stage2 两个阶段。stage1 可以看成是 initial program loaderI( IPL) ,而 stage2 则实现了 grub 的主要功能,包括对特定文件系统的支持(如ext2,ext3,reiserfs 等) ,grub 自己的 shell,以及内部程序(如:kernrl ,initrd ,root)等。stage 1: MBR(512 字节,0 头 0 道
8、 1 扇区) ,前 446 字节存放的是 stage1,后面存放硬盘分区表信息,BIOS 将 stag1 载入内存中 0x7c00 处并跳转执行。stage1(/stage1/start.S)的任务非常单纯,仅仅是将硬盘 0 头 0 道 2 扇区读入内存。0 头 0 道 2 扇区内容是源代码中的/stage2/start.S ,编译后 512 字节,它是 stage2 或者 stage1_5 的入口。注:此时 stage1 是没有能力识别文件系统的,其定位硬盘 0 头 0 道 2 扇区过程如下:BIOS 将 stage1 载入内存 0x7c00 处并执行,然后调用 BIOS INIT13 中断
9、,将硬盘 0 头 0 道2 扇区内容载入内存 0x7000 处,然后调用 copy_buffer 将其转移到内存 0x8000 处。定位 0头 0 道 2 扇区有两种寻址方式:LBA、CHS。start.S 的主要功能是将 stage2 或 stage1_5 从硬盘载入内存,如果是 stage2,则载入 0x820处;如果是 stage1_5,则载入 0x2200 处。注:这里的 stage2 或者 stage1_5 不是/boot 分区/boot/grub 目录下的文件,这个时候 grub 还没有能力识别任何文件系统。分以下两种情况:(1)假如 start.S 读取的是 stage1_5,它
10、存放在硬盘 0 头 0 道 3 扇区向后的位置,stage1_5作为 stage1 和 stage2 中间的桥梁, stage1_5 有识别文件系统的能力,此后 grub 才有能力去访问/boot 分区/boot/grub 目录下的 stage2 文件,将 stage2 载入内存并执行。(2)假如 start.S 读取的是 stage2,同样,这个 stage2 也不是/boot 分区/boot/grub 目录下的stage2,这个时候 start.S 读取的是存放在/boot 分区 Boot Sector 的 stage2。这种情况下就有一个限制:因为 start.S 通过 BIOS 中断方
11、式直接对硬盘寻址(而非通过访问具体的文件系统) ,其寻址范围有限,限制在 8GB 以内。因此这种情况需要将/boot 分区分在硬盘 8GB寻址空间之前。假如是情形(2) ,我们将/boot/grub 目录下的内容清空,依然能成功启动 grub;假如是情形(1) ,将/boot/grub 目录下 stage2 删除后,则系统启动过程中 grub 会启动失败。这个地方经常要进行的操作:是关于 grub 常用的几个指令对应的函数:grubroot (hd0,0) -root 指令为 grub 指定了一个根分区grubkernel /xen.gz-2.6.18-37.el5 -kernel 指令将操作
12、系统内核载入内存grubmodule /vmlinuz-2.6.18-37.el5xen ro root=/dev/sda2 -module 指令加载指定的模块grubmodule /initrd-2.6.18-37.el5xen.img -指定 initrd 文件grubboot -boot 指令调用相应的启动函数启动 OS 内核第三阶段:如阶段 2 所述,grubboot 指令后,系统启动的控制权移交给 kernel。Kernel 会立即初始化系统中各设备并做相关配置工作,其中包括 CPU、I/O 、存储设备等。关于设备驱动加载,有两部分:一部分设备驱动编入 Linux Kernel 中,
13、Kernel 会调用这部分驱动初始化相关设备,同时将日志输出到 kernel message buffer,系统启动后 dmesg 可以查看到这部分输出信息。另外有一部分设备驱动并没有编入 Kernel,而是作为模块形式放在 initrd(ramdisk )中。在 2.6 内核中,支持两种格式的 initrd,一种是 2.4 内核的文件系统镜像 image-initrd,一种是 cpio 格式。以 cpio 格式为例,内核判断 initrd 为 cpio 的文件格式后,会将 initrd 中的内容释放到 rootfs 中。initrd 是一种基于内存的文件系统,启动过程中,系统在访问真正的根文
14、件系统/ 时,会先访问 initrd 文件系统。将 initrd 中的内容打开来看,会发现有bin、devetc 、lib、procsys、sysroot、init 等文件(包含目录) 。其中包含了一些设备的驱动模块,比如 scsi ata 等设备驱动模块,同时还有几个基本的可执行程序 insmod, modprobe, lvm,nash。主要目的是加载一些存储介质的驱动模块,如上面所说的 scsi ideusb 等设备驱动模块,初始化 LVM,把/根文件系统以只读方式挂载。initrd 中的内容释放到 rootfs 中后,Kernel 会执行其中的 init 文件,这里的 init 是一个脚
15、本,由 nash 解释器执行。这个时候内核的控制权移交给 init 文件处理,我们查看 init 文件的内容,主要也是加载各种存储介质相关的设备驱动。驱动加载后,会创建一个根设备,然后将根文件系统/以只读的方式挂载。这步结束后释放未使用内存并执行 switchroot,转换到真正的根/ 上面去,同时运行/sbin/init 程序,开启系统的 1 号进程,此后系统启动的控制权移交给 init 进程。关于 switchroot 是在 nash 中定义的程序。Linux Kernel 需要适应多种不同的硬件架构,但是将所有的硬件驱动编入 Kernel 又是不实际的,而且 Kernel 也不可能每新出
16、一种硬件结构,就将该硬件的设备驱动写入内核。实际上 Linux Kernel 仅是包含了基本的硬件驱动,在系统安装过程中会检测系统硬件信息,根据安装信息和系统硬件信息将一部分设备驱动写入 initrd 。这样在以后启动系统时,一部分设备驱动就放在 initrd 中来加载。第四阶段:init 进程起来后,系统启动的控制权移交给 init 进程。/sbin/init 进程是所有进程的父进程,当 init 起来之后,它首先会读取配置文件 /etc/inittab,进行以下工作:1)执行系统初始化脚本(/etc/rc.d/rc.sysinit) ,对系统进行基本的配置,以读写方式挂载根文件系统及其它文
17、件系统,到此系统基本算运行起来了,后面需要进行运行级别的确定及相应服务的启动;2)确定启动后进入的运行级别;3) 执行 /etc/rc.d/rc,该文件定义了服务启动的顺序是先 K 后 S,而具体的每个运行级别的服务状态是放在/etc/rc.d/rcn.d(n=06)目录下,所有的文件均链接至/etc/init.d 下的相应文件。4)有关 key sequence 的设置5) 有关 UPS 的脚本定义6)启动虚拟终端/sbin/mingetty7)在运行级别 5 上运行 X这时呈现给用户的就是最终的登录界面。至此,系统启动过程完毕:)说明:1)/etc/rc.d/rc.sysint - Sys
18、tem Initialization Tasks它的主要工作有:配置 selinux,系统时钟,内核参数(/etc/sysctl.conf) ,hostname,启用 swap 分区,根文件系统的检查和二次挂载(读写) ,激活 RAID 和 LVM 设备,启用磁盘 quota检查并挂载其它文件系统等等。GRUB 的基本原理以及对 GRUB 的操作控制方法:GRUB 全称为 Grand Unified Boot Loader,是 Linux 操作系统主流的启动引导管理器。主要作用是启动和装载 Linux 操作系统。系统启动过程中一旦完成了 BIOS 自检,GRUB 会被立刻装载。在 GRUB 里
19、面包含了可以载入操作系统的代码以及将操作系统引导权传递给其他启动引导管理器的代码。GRUB 可以允许用户选择使用不同的 kernel 启动系统,或者在启动系统的过程中设置不同的启动参数。而通常 BIOS 会以下面两种方法之一来调用启动引导管理器:将控制权移交给于驱动器主引导记录的 initial program loader(IPL) ;将控制权移交给其他启动引导管理器,再由他们将控制权移交给安装在分区引导扇区的IPL通常情况下启动引导管理器 GRUB 由两部分组成(stage1 和 stage2):stage1 比较小,通常可以驻留在 MBR 或者各个磁盘分区的启动扇区中,主要作用是装载st
20、age2。stage2 比较大,从磁盘的启动引导分区读取至于在 stage1 和 stage2 之间存在一个 stage1.5,是因为 starge1.5 具有识别文件系统的能力。在 Linux 系统中对 GRUB 的配置有两种方法:主要引导管理器:会将启动引导管理器的 stage1 安装在 MBR 上,这时启动引导管理器必须被配置为可以传递控制权到其他操作系统;次要引导管理器:会将启动引导管理器的 stage1 安装在一些分区的引导扇区上,而其他的启动引导管理器会被安装在 MBR 上,由他们来向 Linux 启动引导管理器传递控制权。GRUB 在启动过程中可以提供命令行交互界面,可以从 ex
21、t 系列,reiserfs,fat 等多种文件系统引导系统,并且可以提供密码加密功能,其内容在/boot 分区下,系统启动过程中由配置文件/boot/grub/grub.conf 来定义启动方式,对该配置文件的更改会立即生效。在配置文件/boot/grub/grub.conf 文件中定义的内容包括:grub 所在的分区,引导系统所使用的 kernel 文件位置,硬件初始化使用的 initrd 文件位置,以及启动参数。例如:grubroot (hd0,0) -root 指令为 grub 指定了一个根分区grubkernel /xen.gz-2.6.18-37.el5 -kernel 指令将操作系
22、统内核载入内存grubmodule /vmlinuz-2.6.18-37.el5xen ro root=/dev/sda2 -module 指令加载指定的模块grubmodule /initrd-2.6.18-37.el5xen.img -指定 initrd 文件grubboot -boot 指令调用相应的启动函数启动 OS 内核可见其指定的内容大多数在/boot 分区,如果切换到/boot 分区之后会看到这些内容:/boot/vmlinuz-* linux kernel 的一个 copy;/boot/initrd*.img 初始化的 ram disk 文件/boot/grub/device.
23、map linux 设备名和 grub 设备名的映射文件/boot/grub/grub.conf 主配置文件通常 GRUB 出错几率不是很大,但一旦出现问题恐怕采用最多的方式是重装 grub 到 MBR中。在这种时候需要注意的问题有:首先,设备映射关系:GRUB 里面对设备名称的定义和系统中对设备名称的定义方法不一样:(fd0) /dev/fd0(hd0) /dev/sda /dev/hda(hd1) /dev/sdb /dev/hdb如够进入系统或者救援模式,可执行命令/sbin/grub-install /dev/sda(或者 hda)进行 GRUB重装:# /sbin/grub-inst
24、all device处于某种原因 MBR 中信息出错可以使用上面的命令将其重装到磁盘主引导记录中;但是如果在不能进入系统的情况下就需要通过 grub 的命令行界面进行手动设置,这个时候就要注意上面所提到的映射关系。同时,在 grub 命令行中对 grub 进行手动设置的时候需要注意所使用的命令:# root (hd0,0) -指定启动分区# setup(hd0) -表示将 grub 安装在主引导记录上# quit -退出 grub shell下面是一个完整的 grub.conf 文件内容:rootdhcp-0-195 # cat /etc/grub.conf# grub.conf genera
25、ted by anaconda# Note that you do not have to rerun grub after making changes to this file# NOTICE: You have a /boot partition. This means that# all kernel and initrd paths are relative to /boot/, eg.# root (hd0,0)# kernel /vmlinuz-version ro root=/dev/VolGroup001/LogVol00# initrd /initrd-version.im
26、g#boot=/dev/sdadefault=0timeout=30splashimage=(hd0,0)/grub/splash.xpm.gzhiddenmenupassword -md5 $1$apEcJWbA$DTJ8a6mKn/3yrTTSXBtdH0title Red Hat Enterprise Linux Client (2.6.18-8.1.1.el5)root (hd0,0)kernel /vmlinuz-2.6.18-8.1.1.el5 ro root=/dev/VolGroup001/LogVol00 crashkernel=128M16Minitrd /initrd-2
27、.6.18-8.1.1.el5.img系统启动运行级别的概念以及服务的定制方法;当 initrd 可以正常检测和装载之后,最后的工作就基本上由操作系统来进行了。当系统的init 进程起来之后系统启动的控制权移交给 init 进程。/sbin/init 进程是所有进程的父进程,当 init 起来之后,它首先会读取配置文件 /etc/inittab,进行以下工作:1)执行系统初始化脚本(/etc/rc.d/rc.sysinit) ,对系统进行基本的配置,以读写方式挂载根文件系统及其它文件系统,后面需要进行运行级别的确定及相应服务的启动, (从这个角度可以看出如果要定义系统的 init 动作,需要修
28、改/etc/rc.d/rc.sysinit 脚本)2)通过对/etc/inittab 文件的读取确定启动后进入的运行级别;3) 在相应的运行级别中执行/etc/rc.d/rcx.d 目录下的脚本名称,该文件定义了服务启动的顺序是先 K 后 S,而具体的每个运行级别的服务状态是放在/etc/rc.d/rcn.d(n=06 )目录下,但这些文件均是到/etc/init.d 下的相应文件的链接。系统会按照在该目录下的文件名称和优先级执行对应运行级别目录下的脚本:在某个运行级别的对应目录下,K 开头的服务被关闭,S 开头的服务被开启,K 在 S 开始之前执行,在执行过程中按照数字来定义优先级,数字越低
29、优先级越高。4)按照/etc/rc.d/rcX.d 目录中的定义,系统会于后台启动相应的服务,如果要对某个运行级别中的服务进行更具体的定制,通过 chkconfig 命令来操作,或者通过 setup/ntsys/system-config-services 来进行定制。5)在/etc/inittab 文件中存在有关 key sequence,UPS 的脚本定义,启动虚拟终端/sbin/mingetty 的设置,这时呈现给用户的就是最终的登录界面。也就是说后台启动的服务完毕之后,如果系统默认进入字符界面,则运行 mgetty 进入 1-6号终端控制台,如果系统默认进入图形界面,则开启 gdm 服
30、务进入 7 号虚拟图形控制台。至此,系统启动过程完毕。对于/etc/rc.d/rc.sysinit 文件的说明:/etc/rc.d/rc.sysint - System Initialization Tasks 执行系统初始化任务的脚本。它的主要工作有:配置 selinux,系统时钟,内核参数(/etc/sysctl.conf) ,hostname,启用 swap 分区,根文件系统的检查和二次挂载(读写) ,激活 RAID 和 LVM 设备,启用磁盘 quota检查并挂载其它文件系统这是其基本要实现的工作内容:#!/bin/bash# /etc/rc.d/rc.sysinit - run on
31、ce at boot time# Taken in part from Miquel van Smoorenburgs bcheckrc.# Check SELinux status# Because of a chicken/egg problem, init_crypto must be run twice. /var may be# encrypted but /var/lib/random-seed is needed to initialize swap.# Only read this once.# Initialize hardware# Set default affinity
32、# Load other user-defined modules# Load modules (for backward compatibility with VARs)# Start the graphical boot, if necessary; /usr may not be mounted yet, so we# may have to do this again after mounting# Configure kernel parameters# Set the hostname.# Initialize ACPI bits# RAID setup# Device mappe
33、r the system will reboot* when you leave the shell.Give root password for maintenance(or type Control-D to countinus):在这个界面中输入 root 密码可以在出现的修复模式中运行命令修复。另外一个会造成该现象的原因是在读/etc/fstab 文件并挂载文件系统的时候文件系统检测失败。在这种情况下需要确保文件系统处于 umount 状态下运行 e2fsck。案例六:对 initrd 文件的修复:initrd 是一种基于内存的文件系统,启动过程中,系统在访问真正的根文件系统/ 时,会
34、先访问 initrd 文件系统。将 initrd 中的内容打开来看,会发现有bin、devetc 、lib、procsys、sysroot、init 等文件(包含目录) 。其中包含了一些设备的驱动模块,比如 scsi ata 等设备驱动模块,同时还有几个基本的可执行程序 insmod, modprobe, lvm,nash。主要目的是加载一些存储介质的驱动模块,如上面所说的 scsi ideusb 等设备驱动模块,初始化 LVM,把/根文件系统以只读方式挂载。Linux Kernel 需要适应多种不同的硬件架构,但是将所有的硬件驱动编入 Kernel 又是不实际的,而且 Kernel 也不可能
35、每新出一种硬件结构,就将该硬件的设备驱动写入内核。实际上 Linux Kernel 仅是包含了基本的硬件驱动,在系统安装过程中会检测系统硬件信息,根据安装信息和系统硬件信息将一部分设备驱动写入 initrd 。这样在以后启动系统时,一部分设备驱动就放在 initrd 中来加载。所以在启动过程中 initrd 文件会在 1 号进程被开启之前执行,如果一旦 initrd 文件被破坏或者非正常的更改就会导致系统无法启动。根据以前对 initrd 原理的解释,initrd 中的 init 是使用 nash 解释器去执行,所以系统启动没有到 nash 的时候停住,可以基本上判断是 initrd这里 ha
36、ng 住。比较可行的办法是通过 mkinitrd 命令重建 initrd,生成一个新的用于初始化和装载模块的 ramdisk 镜像。具体的命令是:# mkinitrd f /boot/initrd-.img 例如:# mkinitrd f /boot/initrd-2.6.9-42.ELsmp.img 2.6.9-24.ELsmp或者通过强制的方式重装一个 kernel,因为 kernel 基本上以不变的方式覆盖原来 kernel 所安装的内容,同时会在 rpm 安装 kernel 命令中有重建 initrd 的脚本:rootdhcp-0-195 # rpm -q -scripts kerne
37、lpostinstall scriptlet (using /bin/sh):if uname -i = “x86_64“ -o uname -i = “i386“ ; thenif -f /etc/sysconfig/kernel ; then/bin/sed -i -e s/DEFAULTKERNEL=kernel-smp$/DEFAULTKERNEL=kernel/ /etc/sysconfig/kernel | exit $?fifi/sbin/new-kernel-pkg -package kernel -mkinitrd -depmod -install 2.6.18-8.1.1.
38、el5 | exit $?if -x /sbin/weak-modules then/sbin/weak-modules -add-kernel 2.6.18-8.1.1.el5 | exit $?fipreuninstall scriptlet (using /bin/sh):/sbin/new-kernel-pkg -rminitrd -rmmoddep -remove 2.6.18-8.1.1.el5 | exit $?if -x /sbin/weak-modules then/sbin/weak-modules -remove-kernel 2.6.18-8.1.1.el5 | exi
39、t $?Fi案例七:在系统启动过程中对 rc.sysinit 脚本进行定位的方法:在最近对一些客户问题进行处理的时候有时会发现一些因为对/etc/rc.d/rc.sysinit 脚本的更改而导致系统无法启动成功的问题。由于 rc.sysinit 脚本所负责系统环境变量、存储,设备初始化、配额等多个部分的设置和初始化,所以在启动过程中出现如果是因为 rc.sysinit 的更改而出现 dead lock 不容易定位是哪个地方的设置出现问题。由于 rc.sysinit 脚本是由多个部分组成,一个比较简单的办法就是在每个部分之间加上一个标记。例如:sleep 10echo “sleep 10”这样系
40、统在执行 rc.sysinit 脚本过程中的每个部分都会停 10 秒并显示一个提示信息“sleep 10”,这样可以通过显示的信息定位大概问题出在哪里。案例八:在系统启动过程中出现的初始化和启动 swap 的时候系统出现的 dead lock 的解决方法:在某些情况下系统启动到 enable swap 的时候会长时间的 dead lock 现象,在某些时候系统悬挂于此而始终不能打开 mgetty 终端提供控制台。swap 交换分区是一个特殊的文件系统,该文件系统的基本作用就是可以使操作系统将一部分驻留于内存而暂时不操作的进程转移到 swap 分区中而腾出物理内存给新的需要执行的进程。红帽官方推
41、荐的使用交换分区的比例是 2G 物理内存以下,交换分区为物理内存的 1.5-2 倍;4G 以上物理内存推荐交换分区与物理内存为 1:1。但一般情况下可能会有多种原因造成 swap 文件系统的初始化失败而且由于 swap 分区内容在用户空间无法操作,所以很难准确获得原因。但很多时候系统在启动到 swap 的时候并没有真正的 dead lock,而是由于之后的一些其他服务的启动影响了系统打开终端并给用户造成系统启动 swap 失败的假象。基本上一些启动顺序在 swap 之后的服务都有可能产生这种影响,但由于系统在安装之后默认加载在 kernel parameter “rhgb quite”会掩盖整个的启动过程,所以在系统启动到 GRUB的时候通过进入 GRUB 菜单,手动删除“rhgb quite”会防止在启动的时候屏蔽启动过程并显示完整的启动信息。另外这个 rhgb(redhat graphical boot)本身就有可能干扰后续的服务启动。在很多时候实际上后面的服务已经起来,但是系统会显示 enable swap 并停在该处。在这个时候可以使用ping 的方法或者 ssh 去探测该主机是否已经可以登录并提供服务。