引导过程与服务控制

106 阅读17分钟

本章节重点:

  • Linux操作系统引导过程
  • 会修复系统启动中的三种故障
  • 服务 会写service文件
  • 运行级别 runlevel

一、Linux系统引导过程

引导过程.png

1. 引导过程总览

1.1 开机自检(BIOS)

服务器主机开机以后,将根据主板BIOS中的设置对CPU、内存、显卡、键盘等设备进行初步检测,检测成功后根据预设的启动顺序移交系统控制权,大多时候会移交给本机硬盘。

作用: ①开机检测硬件是否有故障 ②指引硬件去哪里找操作系统(根据bios中设置的开机启动顺序去找操作系统 1本地硬盘 2外接设备 3网卡)

1.2 MBR引导

当从本机硬盘中启动系统时,首先根据硬盘第一个扇区中MBR(主引导记录)的设置,将系统控制权传递给包含操作系统引导文件的分区;或者直接根据MBR 记录中的引导信息调用启动菜单(如 GRUB)。

总结: 运行放在MBR扇区里的启动GRUB引导程序。

1.3 GRUB菜单

对于Linux操作系统来说,GRUB(统一启动加载器)是使用最为广泛的多系统引导器程序。系统控制权传递给GRUB以后,将会显示启动菜单给用户选择,并根据所选项(或采用默认值)加载Linux内核文件,然后将系统控制权转交给内核。

CentOS 7 采用的是 GRUB2 启动引导器。

总结: GRUB引导程序通过读取GRUB配置文件/boot/grub2/grub.cfg,来获取内核和镜像文件系统的设置和路径位置,并屏幕显示grub菜单。(即选择内核文件和系统类型)

bootloader:引导加载器,引导硬件去找到内核(操作系统的核心)

1.4 加载内核(kernel)

Linux内核是一个预先编译好的特殊二进制文件,介于各种硬件资源与系统程序之间,负责资源分配与调度。内核接过系统控制权以后,将完全掌控整个Linux操作系统的运行过程。

CentOS 7系统中,默认的内核文件位于“/boot/vmlinuz-3.10.0-514.el7.x86_64”。

总结: 把内核和镜像文件系统加载到内存中,使其可以使用。

1.5 启动程序

  • centos7 启动的第一个程序 systemd 守护进程
  • centos6 启动的第一个程序 init

init进程初始化: 为了完成进一步的系统引导过程,Linux内核首先将系统中的“/sbin/init”程序加载到内存中运行(运行中的程序称为进程),init 进程负责完成整个系统的初始化,最后等待用户进行登录。

总结: 加载硬件驱动程序,内核把init进程加载到内存中运行

2. 运行级别所对应的 Systemd 目标

运行级别systemd的target说明
0poweroff.target关机状态,使用该级别时将会关闭主机
1rescue.target单用户模式,不需要密码验证即可登录系统,多用于系统维护
2rescue.target用户定义/域特定运行级别。默认等同于3
3multi-user.target字符界面的完整多用户模式,大多数服务器主机运行在此级别
4multi-user.target用户定义/域特定运行级别。默认等同于3
5graphical.target图形界面的多用户模式,提供了图形桌面操作环境
6reboot.target重新启动,使用该级别时将会重启主机

0关机 ; 1 急救模式 ; 2、3、4字符界面 ; 5 图形界面 ; 6 重启 。常用3\color{red}{3}5\color{red}{5}

systemctl  get-default                    #获得当前的运行级别
systemctl  set-default   [unit.target]    #设置指定的target为默认运行级别
systemctl  isolate   [unit.target]        #在不重启的情况下,切换到指定的运行级别

3. 系统初始化进程(init和Systemd介绍)

3.1 init进程

  • 由Linux内核加载运行/sbin/init 程序;
  • init进程是系统中第一个进程;
  • init进程的PID(进程标记)号永远为1。

3.2 Systemd进程

  • Systemd是Linux操作系统中的一种init软件;
  • CentOS7中采用全新的Systemd启动方式,取代传统的SysVinit;
  • CentOS7中运行的第一个init进程是/lib/systemd/systemd

使用 pstree 命令可以查看系统中的所有进程,可以看出systemd是所有进程的父进程。

pstree.png

3.3 init和Systemd区别

先启动systemd 或init ,再启动其他程序

  • init:启动其他程序时是串行,12345678排队启动
  • systemd:启动其他程序时是并行,12345678同时启动

传统init依赖于串行执行Shell 脚本启动服务,导致效率低下,系统启动速度较慢。

systemd能够将更多的服务进程并行启动,并且具有提供按需启动服务的能力,使得启动更少进程,从而提高系统启动速度。

二、解决系统启动中的故障

1. 修复mbr扇区故障

1.1 故障原因和解决思路

故障原因:

  • 病毒、木马的等造成的破坏;
  • 不正确的分区操作、磁盘读写误操作等。

故障现象:

  • 找不到引导程序,启动中断;
  • 无法加载操作系统,开机后黑屏。

解决思路:

  • 提前添加一块新硬盘;
  • 提前做好备份文件(将MBR扇区备份到另一块硬盘上);
  • 以安装光盘引导进入急救模式;
  • 从备份文件中恢复。

1.2 实验 ( MBR扇区备份 )

备份命令:

mkdir /bak
mount /dev/sdb1 /bak
dd if=/dev/sda  of=/bak/mbr.bak  count=512  bs=1      #备份sda系统盘

dd 命令可以对硬盘空间进行备份
dd 命令格式:dd  if=[输入文件] of=[输出文件] [选项]
选项:
bs:指定数据块的大小,也就是定义一次性读取或写入多少字节。模式数据块大小是 512 字节;
count:复制多少次;
skip:从输入文件开头跳过 x个块后再开始复制;
seek:从输出文件开头跳过 x 个块后再开始复制;
conv=标志:依据标志转换文件。

在光盘中恢复MBR扇区命令:

 sh-4.2#  mkdir /bak
 sh-4.2#  mount /dev/sdb1 /bak
 sh-4.2#  dd if=/bak/mbr.bak  of=/dev/sda  count=512  bs=1

实验步骤

  1. 提前添加一块新硬盘,将MBR扇区备份到新硬盘中。

提前添加好新硬/dev/sdb,设置分区sdb1,将sdb1挂载到/mnt目录下,之后将/dev/sda的MBR扇区备份到/mnt目录下。

修复mbr1.png 修复mbr2.png 修复mbr3.png
  1. 破坏MBR分区表,模拟扇区故障.

先查看正常的MBR扇区,之后使用空字符串覆盖掉MBR扇区内容(即/dev/sda的前512字节),再查看破坏后的MBR扇区。最后进行重启,查看能否正常启动。

修复mbr4.png
  1. 重启观察故障情况。因为第一块硬盘的引导程序被破坏,系统自动改用光驱启动。选择Troubleshooting,之后选择rescue mode(急救模式),使用备份文件恢复MBR扇区。

重启发生故障,无法正常启动。当出现安装向导界面时,选择“Troubleshooting”选项 修复mbr5.png

再选择“Rescue a CentOS Linux system”选项,进入急救模式 修复mbr6.png

选择“1”选择 Continue并按 Enter 键继续 修复mbr7.png

再次按 Enter 键后将进入带“sh-4.2#”提示符的 Bash Shell 环境 修复mbr8.png

修复mbr9.png

修复mbr10.png

2. 修复grub引导故障

2.1 故障原因和解决思路

故障原因:

  • MBR中的GRUB引导程序遭到破坏
  • grub.cfg 文件丢失、引导配置有误

故障现象:

  • 系统引导停滞,显示“grup>” 提示符

解决思路:

  • 尝试手动输入引导命令(笨拙繁琐,不建议使用)
  • 提前备份文件,恢复MBR扇区中的grub引导程序
  • 进入急救模式,重写或者从备份中恢复grub.cfg 文件

2.2 实验( 重建grub.cfg 文件 )

重建GRUB菜单配置文件命令

chroot  /mnt/sysimage     
#进入急救模式后,加载光盘镜像,切换到光驱系统的根环境

grub2-install  /dev/sda    
#重新将GRUB引导程序安装到第一块硬盘(dev/sda)的MBR扇区

grub2-mkconfig  -o  /boot/grub2/grub.cfg    
#重新构建GRUB菜单配置文件

实验步骤

  1. 模拟丢失grub.cfg文件

grub修复1.png

  1. 重启观察故障。之后重新启动,在读条界面按 Esc 键(只有0.5秒时间)进入启动菜单,改用光驱启动,引导界面进入急救模式,重建GRUB菜单配置文件。

故障现象:出现 gurb> 提示符 grub修复2.png

重新启动,在读条界面按 Esc 键(只有0.5秒时间)进入启动菜单,改用光驱启动 grub修复3.png

grub修复4.png

引导界面进入急救模式 grub修复5.png

grub修复6.png

重建GRUB菜单配置文件 grub修复7.png

grub修复8.png

3. 忘记root密码

3.1 故障原因和解决思路

故障原因:

  • 遗忘root用户的密码

故障现象:

  • 无法进行需要root权限的管理操作;
  • 若没有其他可用账号,将无法登陆操作系统。

解决思路

  • 进入急救模式,重设密码。

3.2 实验

情况一:

有光驱的情况下,借助光驱里面的操作系统来修改密码,使用光驱启动,进入急救模式。使用root环境,passwd修改root用户密码。

命令:

chroot /mnt/sysimage
#进入急救模式后,更改环境

passwd
#修改密码

情况二:

没有光盘的情况下,启动时按任意键暂停启动,之后按e键进入编辑模式。

将光标移动到 linux 开始的行,添加内核参数 rd.break,之后按ctrl-x启动进入单用户模式。

启动时任意键暂停启动
按e键进入编辑模式
将光标移动linux 开始的行,添加内核参数 rd.break
按ctrl-x启动
mount –o remount,rw /sysroot
chroot /sysroot
passwd root
#如果SELinux是启用的,才需要执行下面操作,如没有启动,不需要执行
touch /.autorelabel
exit
reboot

密码修复1.png

密码修复2.png

密码修复3.png

补充\color{red}{补充}:给grub添加密码,增强安全性

[root@localhost ~]# grub2-setpassword    #直接设置密码

三、 服务

所谓“服务”这类程序,就是要为其他程序或者是用户提供服务的,所以这些服务进程要在系统后台始终处于运行状态,以随时等待被调用。Linux系统中服务名称的最后一般都带有字母d,如 vsftpd,httpd、sshd等,d是英文单词daemon的缩写,表示这是一种守护进程。

按照所服务的对象不同,Linux系统中的服务分为对内和对外两种类型。对内的服务面向的是本地计算机,主要作用是维持本地计算机的正常运行;对外的服务面向的是网络上的用户,主要作用是为网络中的用户提供各种功能。

CentOS系统主要就是用来搭建各种网络服务器,而绝大多数的服务器程序都是以服务的状态在系统中运行的,所以我们所要研究的主要是那些对外提供功能的网络服务。通常情况下,运行了某种对外的服务后,都会在系统中开放相应的端口,如运行了httpd服务后会开放TCP80端口,运行了FTP服务后会开放TCP20,21端口等。关于如何对某种具体的服务进行配置和管理,在这里将要介绍的是如何启动、停止、重启服务等通用操作,而所有这些操作都离不开系统初始化进程systemd。

  • 本地服务程序,管理本机
  • 网络服务程序,接待网络上的客户

1. systemd服务

systemd:管家式的程序,管理系统中其他程序

为了方便管理将系统中的程序按照一定的规则进行管理

1.1 systemd单元类型

在Systemd中不同类型的systemd对象被统一称为单元(unit),是让系统知道该如何进行操作和管理资源的主要对象,所以systemd有许多单元类型。 Systemd单元文件最初默认存放在/lib/systemd/system目录中,每当安装新的软件都会自动在这个目录中添加一个配置文件。通过配置文件进行标识和配置不同单元;文件中主要包含了系统服务、监听。

单元类型护展名说明
Service.service描述一个系统服务软件
Socket.socket描述一个进程间通信的套接字
Device.device描述一个内核识别的设备文件
Mount.mount描述一个文件系统的挂载点
Automoun.automount描述一个文件系统的自动挂载点
Swap.swap描述一个内存交换设备或目录
Timer.timer描述一个定时器(用于实现类似cron的调度任务)
Path.path描述一个文件系统中文件或目录(path 路径)
Snapshot.snapshot用于保存一个systemd的状态(snapshot 快照)
Scope.scope使用systemd的总线接口以编程的方式创建外部进程
Slice.slice描述居于Cgroup的一组通过层次组织的管理系统进程
Target.target描述一组systemd的单元(target 目标)

systemctl 命令用于管理各种类型的systemd单元,可以使用 “systemctl -t help” 命令来查询systemd支持的单元类型。

1.2 系统服务控制 systemctl

systemd 进行管理的时候使用 systemctl命令

命令格式\color{red}{命令格式}:systemctl 控制类型 服务名称

命令效果
systemctl   start  服务名开启服务
systemctl   stop  服务名关闭服务
systemctl   status  服务名查看服务状态
systemctl   restart  服务名重启服务
systemctl   reload  服务名重新加载服务,不影响客户使用
systemctl   enable  服务名开机自启
systemctl   disable  服务名关闭开机自启
systemctl   enable-now  服务名开机自启,并立即启动
systemctl   disable-now  服务名关闭开机自启,并立即关闭

1.3 service unit文件格式

1.3.1 unit 格式说明

  • 以 “#” 开头的行后面的内容会被认为是注释
  • 相关布尔值,1、yes、on、true 都是开启,0、no、off、false 都是关闭
  • 时间单位默认是秒,所以要用毫秒(ms)分钟(m)等须显式说明

1.3.2 service unit file文件组成部分

  • [Unit]:定义与Unit类型无关的通用选项;用于提供unit的描述信息、unit行为及依赖关系等
  • [Service]:与特定类型相关的专用选项;此处为Service类型
  • [Install]:定义由“systemctl enable”以及"systemctl disable“命令在实现服务启用或禁用时用到的一些选项

Unit段的常用选项:

  • Description\color{red}{Description}:描述信息
  • After:定义unit的启动次序,表示当前unit应该晚于哪些unit启动,其功能与Before相反
  • Requires:依赖到的其它units,强依赖,被依赖的units无法激活时,当前unit也无法激活
  • Wants:依赖到的其它units,弱依赖
  • Conflicts:定义units间的冲突关系

Service段的常用选项:

  • Type:定义影响ExecStart及相关参数的功能的unit进程启动类型

simple:默认值,这个daemon主要由ExecStart接的指令串来启动,启动后常驻于内存中

forking:由ExecStart启动的程序透过spawns延伸出其他子程序来作为此daemon的主要服务。原生父程序在启动结束后就会终止

notify:在启动完成后会发送一个通知消息。还需要配合 NotifyAccess 来让 Systemd 接收消息

  • EnvironmentFile:环境配置文件
  • ExecStart\color{red}{ExecStart}:指明启动unit要运行命令或脚本的绝对路径
  • ExecStartPre: ExecStart前运行
  • ExecStartPost: ExecStart后运行
  • ExecStop\color{red}{ExecStop}:指明停止unit要运行的命令或脚本
  • Restart:当设定Restart=1 时,则当次daemon服务意外终止后,会再次自动启动此服务
  • RestartSec: 设置在重启服务( Restart= )前暂停多长时间。 默认值是100毫秒(100ms)。 如果未指
  • 定时间单位,那么将视为以秒为单位。 例如设为"20"等价于设为"20s"。
  • PrivateTmp:设定为yes时,会在生成/tmp/systemd-private-UUID-NAME.service-XXXXX/tmp/目录

Install段的常用选项:

  • WantedBy\color{red}{WantedBy}:被哪些units所依赖,弱依赖
  • Alias:别名,可使用systemctl command Alias.service
  • RequiredBy:被哪些units所依赖,强依赖
  • Also:安装本服务的时候还要安装别的相关服务

1.4 用systemd管理 写service文件

以nginx为例:

mkdir   /data          #新建/data文件夹
cd   /data             #切换到data下
wget http://nginx.org/download/nginx-1.18.0.tar.gz     #官网下载源码包
tar xf nginx-1.18.0.tar.gz                             #解压
yum -y install pcre-devel zlib-devel gcc gcc-c++ make  #安装依赖关系
cd  nginx-1.18.0/                                      #切换到nginx中
./configure   --prefix=/apps/nginx     #检测环境,指定安装目录为/apps/nginx
make                                   #编译
make  install                          #将软件安装进指定的路径
ln -s  /apps/nginx/sbin/nginx     /usr/local/bin       #建立软连接,可以补全nginx   

vim  /lib/systemd/system/nginx.service       #手写.service文件

[Unit]
Description=The nginx HTTP and reverse proxy server

[Service]
Type=forking
PIDFile=/apps/nginx/logs/nginx.pid                #pid文件位置
ExecStart=/apps/nginx/sbin/nginx                  #指明启动unit要运行命令的绝对路径
ExecReload=/apps/nginx/sbin/nginx -s reload       
ExecStop=/usr/bin/kill  -s TERM  ${MAINPID}      #指明关闭unit要运行命令的绝对路径

[Install]
WantedBy=multi-user.target                     #被字符界面所依赖


systemctl  daemon-reload                        #重新加载配置


systemctl  start   nginx        #开启服务
systemctl  status  nginx        #查看服务状态
systemctl  stop    nginx        #开启服务
systemctl  status   nginx       #查看服务状态

2. init服务

init (daemon守护进程)想要管理其他服务, 需要手写脚本 , 不能复制粘贴
(了解,在centos6 上用的较多)

以nginx为例:

wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar xf nginx-1.18.0.tar.gz 
yum -y install pcre-devel zlib-devel gcc gcc-c++ make
cd  nginx-1.18.0/
./configure  --prefix=/usr/local/nginx
make -j2 && make install
ln -s /usr/local/nginx/sbin/nginx  /usr/local/sbin/
#这步可以不做,做软链接,让系统可以直接使用

cd  /etc/init.d/
vim /etc/init.d/nginx     #写一个脚本

#!/bin/bash 
#chkconfig: - 99 20        # - 代表全部启动;第99个启动;第20个关闭
#description:Nginx Service Control Script 
PROG="/usr/local/nginx/sbin/nginx"       #主程序的绝对路径
PIDF="/usr/local/nginx/logs/nginx.pid"   #安装好nginx软件后并且启动后,会自动将自己的pid号存到该文件中

case "$1" in
start) $PROG 
;; 
stop) 
kill -s QUIT $(cat $PIDF)            # $( )  调用命令执行的结果
;; 
restart) 
$0 stop $0 start
;; 
reload) 
kill -s HUP $(cat $PIDF)             #kill 发信号
;;
*) echo "Usage: $0 {start|stop|restart|reload}" 
exit 1 
esac 
exit 0

chmod +x /etc/init.d/nginx 
#给脚本加上权限
ss -ntap |grep nginx
#查看服务有没有启动

chkconfig --add nginx
#将服务加入 init
chkconfig --list  nginx
#查看服务
chkconfig --level 35 nginx on
#开启3和5自动开启

补充: 怎么知道nginx.pid文件是否存在呢?使用 [ ] 命令判断一个文件是否存在

判断.png

chkconfig

  • 在centos6 中,init 进行管理的时候使用 chkconfig 命令
  • 在centos7 中,systemd 进行管理的时候使用 systemctl命令

centos7上也支持 chkconfig ,但是不推荐使用

命令格式:

chkconfig --list  [服务名称]    #显示所有运行级系统服务的运行状态信息(on或off)
chkconfig --add 服务名称        #增加一项新的服务
chkconfig --level 级别 服务名称 on/off

例如
chkconfig --list  nginx        #查看服务
chkconfig --add httpd          #增加httpd服务
chkconfig --level 35 httpd on  #设置nginx在运行级别为3、5的情况下都是on(开启)的状态

3. Linux系统的运行级别

1. 查看运行级别

  • runlevel命令 runlevel只能查看切换运行级别与当前运行级别
[root@localhost ~]# runlevel     //查看切换运行级别与当前运行级别
 N 5

 #N:表示前一次没有切换过运行级别
 #5:当前运行级别5,处于图像界面的多用户模式
  • systemctl工具 systemctl能查看默认的运行级别
[root@localhost ~]# systemctl get-default    //查看默认的运行级别
graphical.target                             //默认运行级别为图形界面

2. 临时切换运行级别

  • init命令 init的命令参数是运行级别所对应的数字
init 0     //关机
init 1     //切换到单用户模式(single,维护模式)
init 3     //切换到字符界面的多用户模式
init 5     //切换到图形界面的多用户模式
init 6     //重启
  • systemctl工具 systemctl的命令参数是具体的target
systemctl  [command]  [unit.target]
systemctl  get-default                    #获得当前的运行级别
systemctl  set-default   [unit.target]    #设置指定的target为默认运行级别
systemctl  isolate   [unit.target]        #在不重启的情况下,切换到指定的运行级别

systemctl isolate poweroff.target     //关机
systemctl isolate rescue.target       //切换到单用户模式(single,维护模式)     
systemctl isolate multi-user.target   //切换到字符界面的多用户模式      
systemctl isolate graphical.target    //切换到图形界面的多用户模
systemctl isolate reboot.target       //重启

临时切换运行级别,使用 init 命令更为方便

3. 设置永久运行级别

使用 systemctl set-default 命令

 [root@localhost ~]# systemctl get-default     //查看当前默认运行级别,为图形界面
 graphical.target
 [root@localhost ~]# systemctl set-default multi-user.target     //将默认运行级别修改为字符界面
 Removed symlink /etc/systemd/system/default.target.
 Created symlink from /etc/systemd/system/default.target to /usr/lib/systemd/system/multi-user.target.
 [root@localhost ~]# systemctl get-default     //查看修改后的默认运行级别,为字符界面
 multi-user.target