Linux启动流程和内核管理

CentOS 6 启动流程

 

  1. 加载BIOS的硬件信息,获取第一个启动设备

  2. 读取第一个启动设备MBR的引导加载程序(grub)的启动信息

  3. 加载核心操作系统的核心信息,核心开始解压缩,并尝试驱动所有的硬件设备

  4. 核心执行init程序,并获取默认的运行信息

  5. init程序执行/etc/rc.d/rc.sysinit文件,重新挂载根文件系统

  6. 启动核心的外挂模块

  7. init执行运行的各个批处理文件(scripts)

  8. init执行/etc/rc.d/rc.local

  9. 执行/bin/login程序,等待用户登录

  10. 登录之后开始以Shell控制主机

硬件启动POST

BIOS

Basic Input and Output System(基本输入输出系统),保存着有关计算机系统最重要的基本输入输出 程序,系统信息设置,开机加电自检程序和系统启动自举程序等。

BIOS 就是一个程序,其代码存储在主板的一颗ROM存储芯片上,ROM是只能读不能写的,这颗芯片上 的BIOS程序,在主板出厂的时候,己经固化好了,所以不管断不断电,这个BIOS程序都会一直存储在这 颗芯片上。

当我们修改了BIOS里面的某些设置时,这个修改的数据是存储在另外一颗RAM存储芯片上,RAM掉电后 数据就会消失,所以主板上有一颗纽扣电池来给这个RAM供电,当这颗纽扣电池没电了,BIOS里面的设 置项,就又恢复成出厂设置了。

POST

Power-On-Self-Test (加电自检),是BIOS程序中的一个主要功能,负责完成对CPU、主板、内存、硬 盘子系统、显示子系统、串并行接口、键盘等硬件情况的检测。

ROM

Read-Only Memory (只读存储),该存储器上的数据只能读出,不能写入,其存储的数据一般在硬件 出厂时就写入固定下来了,所以即使切断电源,数据也不会丢失,所以又称为固定存储器。

RAM

Random Access Memory (随机存取存),这里的随机取存,是指通电后,随时可在任意位置单元存 取数据信息,不过断电后内部信息也随之消失。

所以 对于一台计算机来讲,通电后第一件事件就是运行BIOS程序,BIOS程序最先做的,就是对硬件执行 POST(加电自检),如果硬件自检不通过,会显示相应的错误,还会有相应的蜂鸣音。

启动加载器 bootloader

bootloader 基本概念

Bootloader

引导加载器,引导程序。

是底层硬件与上层应用软件(操作系统)之间的一个中间接口软件。

它不是BIOS中的功能,也不是操作系统中的功能,它是一个独立的软件,运行在BIOS之后,操作系统启动之前。

它的主要作用就是引导操作系统启动。

Bootloader 是一个独立软件,可以单独安装,

但在一般情况下,安装操作系统时,也会一起安装Bootloader程序

不同的操作系统,会安装不同的Bootloader程序

WIndows中的Bootloader

ntloader 仅用来启动OS

Linux中的Bootloader

功能丰富,提供菜单,允许用户选择要启动系统或不同的内核版本;把用户选定的内核装载到内存中的 特定空间中,解压、展开,并把系统控制权移交给内核

LILO:LInux LOader,早期的bootloader,功能单一

GRUB:GRand Unified Bootloader,CentOS 5,6 GRUB 0.97(GRUB Legacy), CentOS 7 以后使 用 GRUB 2.02

系统的启动引导方式有两种,分别是BIOS模式和UEFI模式:

在BIOS模式下,Bootloader第一阶段的程序(代码)存储在硬盘0磁道0扇区的前446个字节的空间内,由 第一阶段的程序来引导第二阶段的bootloader程序,像ntloader,LILO,GRUB等都是采用这种分段执 行的方式。

在UEFI模式下,直接由EFI系统分区中的 .efi 引导程序来引导操作系统。

grub 功能和组成

GRUB 启动阶段

阶段阶段顺序存储位置和功能
primary boot loader1st stage存储在0磁道0扇区的前446字节空间内
primary boot loader1.5 stage1扇区到2047扇区,存储2阶段的文件系统驱动,保证2nd中 的文件可读
secondary boot loader2 stage/boot/grub/grub.conf

grub 配置文件

[root@c6 ~]# ll /etc/grub.conf 
lrwxrwxrwx. 1 root root 22 Aug 29 05:50 /etc/grub.conf -> ../boot/grub/grub.conf
[root@c6 ~]# cat /boot/grub/grub.conf 
# grub.conf generated 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/mapper/vg_c6-lv_root
#         initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.32-71.el6.x86_64)
 root (hd0,0)
 kernel /vmlinuz-2.6.32-71.el6.x86_64 ro root=/dev/mapper/vg_c6-lv_root 
rd_LVM_LV=vg_c6/lv_root rd_LVM_LV=vg_c6/lv_swap rd_NO_LUKS rd_NO_MD rd_NO_DM 
LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYBOARDTYPE=pc KEYTABLE=us 
crashkernel=auto rhgb quiet
 initrd /initramfs-2.6.32-71.el6.x86_64.img

主要配置项说明

选项说明
default0默认使用哪个系统启动,0表示第一个
timeout5启动界面项选择项停留时长
splashimage(hd0,0)/grub/splash.xpm.gz背景图片,可自定义路径和文件
password[--md5|encrypt] STRING启动菜单编辑认证
hiddenmenu表示默认隐藏选择菜单
titleCentOS (2.6.32- 71.el6.x86_64)菜单选择的标题,一个title表示一个系统,一 台机可以有多个系统
root (hd0,0)/boot 所在的设备和分区,hd0,0表示第一块 磁盘第一个分区
kernel /vmlinuz-2.6.32- 71.el6.x86_64内核文件路径,以/boot为根目录
root=/dev/mapper/vg_c6- lv_root操作系统根目录挂载设备
initrd /initramfs-2.6.32- 71.el6.x86_64.img临时根系统,包含驱动,常用工具等
password [--md5 encrypt] STRING启动选定的内核或操作系统时进行认证

init进程

init进程是一个由内核启动的用户级进程。

内核启动(己被载入内存,开始运行,并己经初始化了所有设备驱动和数据结构等)之后,就通过启动 一个用户级的程序 /sbin/init来完成引导进程。

/sbin/init 程序是内核启动之后的第一个进程,也是进程树中的树根,所以其进程ID始终为1 。

但是这里有一个问题

/sbin/init 程序的功能之一就是要挂载整个根文件系统, /sbin/init 这个程序的可执行文件,它自 己也是在根文件系统里面,

也就是说,得先运行 /sbin/init 程序才有文件目录结构树,但是得先有目录结构,才能通过 /sbin/init 这个路径找到可执行文件

initrd机制

initramfs:(init ram filesystem) 初始 ram 文件系统

是在内核启动的早期提供一个用户态环境,用于完成在内核启动阶段不易完成的工作

通过此系统先形成一个精简版的linux系统,里面包含常用的文件系统的驱动,以及常用的工具和命令, 然后再挂载真正的根文件系统,再定位到 /sbin/init 程序,从而完在真正的启动。

grub 管理

启动界面的grub管理

该界面的默认项由 /boot/grub/grub.conf 中的配置项决定,用户可在此界面输入命令进行操作。

选择键作用
上下方向键选择不同的操作系统启动
ESC键返回主界面
a修改内核参数
c进入grub交互式界面
e修改当前选中系统的启动参数
p密码校验
e --> b启动系统
e --> e修改选中项
e --> o添加新行
e --> d删除行

grub 修复

删除整个boot目录下的所有文件

[root@c6 ~]# ls /boot/
config-2.6.32-71.el6.x86_64 initramfs-2.6.32-71.el6.x86_64.img System.map2.6.32-71.el6.x86_64
efi                         lost+found                         vmlinuz-2.6.32-
71.el6.x86_64
grub                         symvers-2.6.32-71.el6.x86_64.gz
#删除
[root@c6 ~]# rm -rf /boot/*
[root@c6 ~]# ls /boot/

重启,从光盘启动,进入救援模式

选择shell

执行下列命令

chroot /mnt/sysimage/
grub-install /dev/sda
mount /dev/sr0 /mnt
rpm -ivh /mnt/Packages/kernel-2.6.32-71.el6.x86.rpm --force
vim /boot/grub/grub.conf
default=0
timeout=5
hiddenmenu
title CentOS6
       root (hd0,0)
       kernel /vmlinuz-2.6.32-71.el6.x86_64 ro root=/dev/mapper/vg_c6-lv_root 
       initrd /initramfs-2.6.32-71.el6.x86_64.img
sync
sync
exit
exit

再次重启,硬盘启动即可

grub修复总结

阶段:第1阶段

原因:磁盘分区上的第一阶段二进制数数据被破坏

修复:光盘启动,进救援模式,重装grub 即可

chroot /mnt/sysimage/
grub-install /dev/sda
sync
sync
exit
exit

阶段:第1.5阶段

原因:磁盘分区上的第1.5阶段二进制数数据被破坏

修复:同上

阶段:第2阶段

原因: /boot/grub/ 目录内的文件丢失,或 /boot/ 目录下的文件丢失

修复:光盘启动,进救援模式,重装grub,重装内核,手写 /boot/grub/grub.conf ,然后重启

chroot /mnt/sysimage/
grub-install /dev/sda
mount /dev/sr0 /mnt
rpm -ivh /mnt/Packages/kernel-2.6.32-71.el6.x86.rpm --force

vim /boot/grub/grub.conf
default=0
timeout=5
hiddenmenu
title CentOS6
       root (hd0,0)
       kernel /vmlinuz-2.6.32-71.el6.x86_64 ro root=/dev/mapper/vg_c6-lv_root 
       initrd /initramfs-2.6.32-71.el6.x86_64.img
       
sync
sync
exit
exit

 

grub 安装

centos6中的 grub 有两种安装方式,分别是 grub-install 命令和 grub交互式命令

grub-install 安装grub stage1和stage1_5到/dev/DISK磁盘上,并复制GRUB相关文件到 DIR/boot目录 下

grub-install --root-directory=DIR /dev/DISK

grub命令

[root@c6 ~]# grub
grub> root (hd0,0)
grub> setup (hd0)
grub> quit

grub常用命令

help 						#获取帮助列表
help KEYWORD 				#获取指定内容帮助
root (hd#,#) 				#指定操作系统所在的设备和分区
kernel /PATH/TO/KERNEL_FILE #指定kernel文件位置,后面可以加参数
initrd /PATH/TO/INITRAMFS_FILE #设定为选定的内核提供额外文件的ramdisk
boot 						#使用选中的内核启动

查看当前启动内核的启动时的参数

[root@c6 ~]# cat /proc/cmdline 
ro root=/dev/mapper/vg_c6-lv_root

手动在grub命令行下指定内核并启动

grub> root (hd#,#)
grub> kernel /vmlinuz-VERSION-RELEASE ro root=/dev/DEVICE 
grub> initrd /initramfs-VERSION-RELEASE.img
grub> boot

grub识别硬盘的方式

(hd0,0) 	#第一块硬盘第一个分区

hd0 		#磁盘编号,用数字表示, 从0开始编号
0 			#分区编号,用数字表示, 从0开始编号
grub 安全

破解centos6 中的 root口令

  1. 编辑grub菜单(选定要编辑的title,而后使用a 或 e 命令)

  2. 在选定的kernel后附加参数 1(s|S|single),此参数是用来进入单用户模式

  3. 在kernel所在行,敲 b 键,以此配置启动,即可无密码以root身份进入系统

设置grub密码,防止破解系统root密码

grub 密码生成工具

 

grub-md5-crypt
grub-crypt


#查看grub工具
[root@c6 ~]# grub
grub           grubby         grub-install   grub-md5-crypt grub-terminfo   
#使用md5工具生成密文
[root@c6 ~]# grub-md5-crypt 
Password: 
Retype password: 
$1$B0do8$z5jKhXah4sInKxPGQRQWE0
[root@c6 ~]# 
[root@c6 ~]# vim /etc/grub.conf
default=0
timeout=5
password --md5 $1$B0do8$z5jKhXah4sInKxPGQRQWE0
title Centos6
   root (hd0,0)
   kernel /vmlinuz-2.6.32-71.el6.x86_64 ro root=/dev/mapper/vg_c6-lv_root
   initrd /initramfs-2.6.32-71.el6.x86_64.img

 想再次编辑grub,就需要密码认证

生成grub启动背景图片

[root@c6 ~]# convert -resize 640x480 -colors 14 winner.png splash.xpm
[root@c6 ~]# more splash.xpm
#生成splash.xpm.gz
[root@c6 ~]# gzip   splash.xpm 
[root@c6 ~]# mv splash.xpm.gz /boot/grub

加载 kernel

kernel 自身初始化过程

  1. 探测可识别到的所有硬件设备

  2. 加载硬件驱动程序(借助于ramdisk加载驱动)

  3. 以只读方式挂载根文件系统

  4. 运行用户空间的第一个应用程序:/sbin/init

Linux内核特点:

  • 支持模块化:.ko(内核对象),如:文件系统,硬件驱动,网络协议等

  • 支持内核模块的动态装载和卸载

内核组成部分:

  • 核心文件:/boot/vmlinuz-VERSION-release

ramdisk:辅助的伪根系统,加载相应的硬件驱动,ramdisk --> ramfs 提高速度
CentOS 5 /boot/initrd-VERSION-release.img
CentOS 6 以后版本 /boot/initramfs-VERSION-release.img
  • 模块文件:/lib/modules/VERSION-release

误删除内核文件/boot/vmlinuz-2.6.32-754.el6.x86_64无法启动,故障恢复

[root@centos6 ~]#rm -f /boot/vmlinuz-2.6.32-754.el6.x86_64
[root@centos6 ~]#reboot
#进入rescue模式
#chroot /mnt/sysimage
#mount /dev/sr0 /mnt/
#cp /mnt/isolinux/vmlinuz /boot/vmlinuz-2.6.32-754.el6.x86_64
#sync
#exit
#reboot

ramdisk文件的制作:

mkinitrd命令

mkinitrd /boot/initramfs-$(uname -r).img $(uname -r)

dracut命令

dracut /boot/initramfs-$(uname -r).img $(uname -r)

误删除/boot/initramfs-2.6.32-754.el6.x86_64.img无法启动,故障恢复

[root@centos6 ~]#rm -f /boot/initramfs-2.6.32-754.el6.x86_64.img
[root@centos6 ~]#reboot
#进入rescue模式
#chroot /mnt/sysimage
#mkinitrd /boot/initramfs-$(uname -r).img $(uname -r)
#sync
#exit
#exit
#reboot

init初始化

/sbin/init 程序是内核启动之后的第一个进程,也是进程树中的树根,所以其进程ID始终为1

init程序的类型:

适用系统配置文件
SysvinitCentOS5以及之前/etc/inittab
upstartCentOS6/etc/initab,/etc/init/*.conf
CentOS7以及之后/usr/lib/systemd/systemd

CentOS6中的init

[root@c6 ~]# which init
/sbin/init

[root@c6 ~]# rpm -qf /sbin/init
upstart-0.6.5-6.1.el6.x86_64
运行级别

运行级别:为系统运行或维护等目的而设定;0-6:7个级别,一般使用3, 5做为默认级别

运行级别说明
0关机
1单用户模式(root自动登录),single,维护模式
2多用户模式,启动网络功能,但不会启动NFS;维护模式
3多用户模式,正常模式;文本界面
4预留级别;可同3级别
5多用户模式,正常模式;图形界面
6重启

查看现在使用的默认级别

[root@c6 ~]# cat /etc/inittab 
#
#
# Default runlevel. The runlevels used are:
#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)
# 
id:5:initdefault:

切换级别

init N

相关配置文件

CentOS 6 init程序为 upstart, 其配置文件/etc/inittab, /etc/init/*.conf,配置文件的语法遵循 upstart配 置文件语法格式

/etc/inittab #设置系统默认的运行级别
/etc/init/control-alt-delete.conf
/etc/init/tty.conf
/etc/init/start-ttys.conf
/etc/init/rc.conf
/etc/init/prefdm.conf
......
初始化脚本 sysinit

系统初始化脚本功能

  1. 设置主机名

  2. 设置欢迎信息

  3. 激活udev和selinux

  4. 挂载/etc/fstab文件中定义的文件系统

  5. 检测根文件系统,并以读写方式重新挂载根文件系统

  6. 设置系统时钟

  7. 激活swap设备

  8. 根据/etc/sysctl.conf文件设置内核参数

  9. 激活lvm及software raid设备

  10. 加载额外设备的驱动程序

  11. 清理操作

服务管理

/etc/rc.d/rc 控制服务脚本的开机自动运行

K(kill) 开头表示关闭服务,K后面的数字表示运行顺序,数字越小,越先运行,表示越先被停止,这类服 务通常是要依赖其它服务

S(start) 开头表示开启服务,S后面的数字表示运行顺序,数字越小,越先运行,表示越先被启动,这类 服务通常是要被其它服务依赖

chkconfig 命令管理服务
chkconfig [--list] [--type <type>] [name]
chkconfig --add <name>
chkconfig --del <name>
chkconfig --override <name>
chkconfig [--level <levels>] [--type <type>] <name> 
<on|off|reset|resetpriorities> #--level 默认为2,3,4,5

#范例:
#查看所有服务在不同运行级别下的停启情况
[root@c6 ~]# chkconfig --list
NetworkManager 0:off 1:off 2:on 3:on 4:on 5:on 6:off
abrtd         0:off 1:off 2:off 3:on 4:off 5:on 6:off
acpid         0:off 1:off 2:on 3:on 4:on 5:on 6:off
atd           0:off 1:off 2:off 3:on 4:on 5:on 6:off
......

#查看指定服务
[root@c6 ~]# chkconfig --list crond
crond         0:off 1:off 2:on 3:on 4:on 5:on 6:off

#查看链接
[root@c6 ~]# ll /etc/rc3.d/*cron*
lrwxrwxrwx. 1 root root 15 Aug 29 05:40 /etc/rc3.d/S90crond -> ../init.d/crond

#修改服务
[root@c6 ~]# chkconfig --level 3 crond off

#再次查看,变成了K开头
[root@c6 ~]# ll /etc/rc3.d/*cron*
lrwxrwxrwx. 1 root root 15 Aug 30 14:49 /etc/rc3.d/K60crond -> ../init.d/crond

#crond在3模式下变成了off
[root@c6 ~]# chkconfig --list crond
crond         0:off 1:off 2:on 3:off 4:on 5:on 6:off
服务脚本

服务脚本放在 /etc/init.d/ 目录下,除了 #!/bin/sh 机制外,还要有 chkconfig 和 description 项

#!/bin/bash
#chkconfig: LLLL nn nn   #LLLL 表示初始在哪个级别下启动,-表示都不启动,nn表示数字
#description: #描述信息
......

#范例:
#Start是S90,Kill是K60, 90/60 是定义在对应的脚本文件中
[root@c6 ~]# ll /etc/rc3.d/*cron*
lrwxrwxrwx. 1 root root 15 Aug 29 05:40 /etc/rc3.d/S90crond -> ../init.d/crond
[root@c6 ~]# ll /etc/rc3.d/*cron*
lrwxrwxrwx. 1 root root 15 Aug 30 14:49 /etc/rc3.d/K60crond -> ../init.d/crond

#查看脚本文件
[root@c6 ~]# cat /etc/init.d/crond
#!/bin/sh
#
# crond         Start/Stop the cron clock daemon.
#
# chkconfig: 2345 90 60 表示默认
2345是S90, 其它模式是K60
# description: cron is a standard UNIX program that runs user-specified \
#             programs at periodic scheduled times. vixie cron adds a \
#             number of features to the basic UNIX cron, including better \
#             security and more powerful configuration options.
......

自定义服务脚本

#创建服务脚本
[root@c6 ~]# vim /etc/init.d/testsrv
#!/bin/bash

# chkconfig: - 96 3
# description: This is test service script

. /etc/init.d/functions
start(){
   [ -e /var/lock/subsys/testsrv ] && exit || touch /var/lock/subsys/testsrv
    echo $PATH
   action "Starting testsrv"
    sleep 3000 &
}
stop(){
   [ -e /var/lock/subsys/testsrv ] && rm /var/lock/subsys/testsrv || exit
   action "Stopping testsrv"
}
status(){
   [ -e /var/lock/subsys/testsrv ] && echo "testsrv is running..." || echo
"testsrv is stopped"
}
case $1 in
 start)
 start
 ;;
 stop)
 stop
 ;;
 restart)
 stop
 start
 ;;
 status)
 status
 ;;
 *)
  echo $"Usage $0 {start|stop|status|restart}"
 exit 2
esac
#加可执行权限
[root@c6 ~]# chmod a+x /etc/init.d/testsrv

#添加服务
[root@c6 ~]# chkconfig --add testsrv

#查看
[root@c6 ~]# chkconfig --list testsrv
testsrv       0:off 1:off 2:off 3:off 4:off 5:off 6:off

#开机启动
[root@c6 ~]# chkconfig testsrv on
[root@c6 ~]# chkconfig --list testsrv
testsrv       0:off 1:off 2:on 3:on 4:on 5:on 6:off

#启动
[root@c6 ~]# service testsrv start
/sbin:/usr/sbin:/bin:/usr/bin
Starting testsrv                                           [ OK ]

#停止
[root@c6 ~]# service testsrv stop
Stopping testsrv                                           [ OK ]

#删除服务
[root@c6 ~]# chkconfig --del testsrv

service 命令手动管理服务

service < option > | --status-all | [ service_name [ command | --full-restart ] ]

#示例:
[root@c6 ~]# service crond stop
Stopping crond:                                           [ OK ]
[root@c6 ~]# service crond start
Starting crond:                                           [ OK ]
[root@c6 ~]# service crond startt
Usage: /etc/init.d/crond {start|stop|status|restart|condrestart|tryrestart|reload|force-reload}
[root@c6 ~]# service crond status
crond (pid  1756) is running...
非独立服务

有很多服务不是常用服务,使用频率不高,如果这种服务也加入开机启动,则会消耗服务器资源, 为了平衡资源与服务使用之间的关系,我们可以用一个代理服务来管理这些不常用的服务。

这些被代理的服务就称之为非独立服务

一般用 xinetd 服务来管理非独立服务,默认没有安装xinetd,但当安装非独立服务时,就会安装xinetd 服务

[root@c6 ~]# rpm -qi xinetd
package xinetd is not installed

#安装非独立服务telnet-server
[root@c6 ~]# yum install -y telnet-server
[root@c6 ~]# rpm -ql telnet-server
/etc/xinetd.d/telnet
/usr/sbin/in.telnetd
/usr/share/man/man5/issue.net.5.gz
/usr/share/man/man8/in.telnetd.8.gz
/usr/share/man/man8/telnetd.8.gz

[root@c6 ~]# rpm -q xinetd
xinetd-2.3.14-29.el6.x86_64
开机启动文件 rc.local

正常级别下,最后启动一个服务S99local没有链接至/etc/rc.d/init.d一个服务脚本,而是指向 了/etc/rc.d/rc.local脚本

不便或不需写为服务脚本放置于/etc/rc.d/init.d/目录,且又想开机时自动运行的命令,可直接放置 于/etc/rc.d/rc.local文件中

/etc/rc.d/rc.local在指定运行级别脚本后运行

注意:默认Ubuntu 无 /etc/rc.local 文件,需要手动创建并添加可执行权限,首行必须有shebang机制

CentOS 6 启动过程总结

POST 					#加电自检
boot loader 			#引导启动内核
vmlinux(initrd /initramfs-2.6.32-71.el6.x86_64.img) #临时系统
rootfs 					#根文件系统
/sbin/init 				#执行init程序
/etc/inittab 			#设置默认运行级别
/etc/rc.d/rc.sysinit 	#运行系统初始脚本完成系统初始化
/etc/rcN.d/KNN 			#当前级别下需要停止的服务
/etc/rcN.d/SNN 			#当前级别下需要启动的服务
/etc/rc.d/rc.local 		#没加服务的自定义开机启动项设置登录终端

systemd 和启动流程

systemd 特性

Systemd:从 CentOS 7 版本之后开始用 systemd 实现init进程,系统启动和服务器守护进程管理器, 负责在系统启动或运行时,激活系统资源,服务器进程和其它进程

Systemd 新特性

  • 系统引导时实现服务并行启动

  • 按需启动守护进程

  • 自动化的服务依赖关系管理

  • 同时采用socket式与D-Bus总线式激活服务

  • socket与服务程序分离

  • 向后兼容sysv init脚本

  • 使用systemctl 命令管理,systemctl命令固定不变,不可扩展,非由systemd启动的服务, systemctl无法与之通信和控制

  • 系统状态快照

systemd 中的 unit

unit表示不同类型的systemd对象,通过配置文件进行标识和配置;

文件中主要包含了系统服务、监听socket、保存的系统快照以及其它与init相关的信息

查看Unit类型

#查看unit类型
[root@ubuntu ~]# systemctl -t help
Available unit types:
service
mount
swap
socket
target
device
automount
timer
path
slice
scope

常见Unit类型说明

unit类型后缀作用
service.service定义系统服务
socket.socket定义进程间通信用的socket文件,可以延迟启动,按需启动
target.target不同服务的集合,用于模拟运行级别
device.device用于定义内核识别的设备
mount.mount定义文件系统挂载点
automount.automount文件系统的自动挂载点
swap.swap用于标识swap设备
timer.timer用于安排激活另一个单元的计时器
path.path用于定义文件系统中的文件或目录,常用于当文件系统变化时, 延迟激活服务,如spool 目录
slice.slice通过 Linux 控制组节点 (cgroups) 限制资源
scope.scopesystemd 总线接口的信息,常用于管理外部系统进程

unit的配置文件

/usr/lib/systemd/system/ #每个服务最主要的脚本文件目录,类似于之前的/etc/init.d/
/run/systemd/system/ #系统执行过程中所产生的服务脚本,比上面目录优先运行
/etc/systemd/system/ #管理员建立的执行脚本,类似于/etc/rcN.d/Sxx的功能,比上面目录优先运行

范例:列出所有在内存中的单元

#systemctl 或 systemctl list-units
[root@ubuntu ~]# systemctl
 UNIT                                               LOAD   ACTIVE SUB       
DESCRIPTION               
 sys-devices-virtual-block-dm\x2d0.device           loaded active plugged   
/sys/devices/virtual/block>
 sys-subsystem-net-devices-virbr0.device           loaded active plugged   
/sys/subsystem/net/devices>
  -.mount                                           loaded active mounted   
Root Mount                
 boot.mount                                         loaded active mounted   
/boot                      
 dev-mqueue.mount                                   loaded active mounted   
POSIX Message Queue File S>
 home.mount                                         loaded active mounted   
/home    
 ......

范例:列出所有己加载到内存的 service

#systemctl list-units --type=service -a 或 systemctl --type=service --all
[root@ubuntu ~]# systemctl list-units --type=service -a
 UNIT                               LOAD     ACTIVE   SUB     DESCRIPTION
 accounts-daemon.service           loaded   active   running Accounts Service
 alsa-restore.service               loaded   inactive dead   Save/Restore 
Sound Card State
● apparmor.service                   not-found inactive dead   apparmor.service
 atd.service                       loaded   active   running Job spooling 
tools
 auth-rpcgss-module.service         loaded   inactive dead   Kernel Module 
supporting RPCSEC_GSS
 avahi-daemon.service               loaded   active   running Avahi mDNS/DNS-SD 
Stack
 blk-availability.service           loaded   inactive dead   Availability of 
block devices
● cloud-init-local.service           not-found inactive dead   cloud-initlocal.service
 ......

字段说明

字段说明
UNIT服务名称
LOAD加载状态 loaded|not-found|bad-setting|error|masked
ACTIVE服务状态 active|reloading|inactive|failed|activating|deactivating
SUB详细状态,与 LOAD和ACTIVE列有关,具体可执行 systemctl --state=help 查看
DESCRIPTIONunit 描述信息

service 系统服务管理

systemctl COMMAND name.service [name2.service] ...

常用操作

操作类型systemctl 命令service 命 令
启动服务systemctl start name1.service[name2.service]service name start
停止服务systemctl stop name.serviceservice name stop
重启服务systemctl restart name.serviceservice name restart
查看状态systemctl status name.serviceservice name status
禁止服务启动systemctl mask name.service
恢复可启动systemctl unmask name.service
当前是否是可启动状态systemctl is-active name.service
查看service服务脚本内容systemctl cat name.service
查看所有已经激活的服务systemctl list-units--type service | -t service
查看所有服务systemctl list-units--type service | -t service -all | -a
设定服务开机启动systemctl enable name.servicechkconfig name on
设定服务开机禁止启动systemctl disable name.servicechkconfig name off
查看所有服务开机启动状态systemctl list-unit-files --type service --all | -achkconfig -- list
查看服务在不同运行级别下的启用禁用ls /etc/systemd/system/*.wants/name.servicechkconfig - list name
查看服务是否开机自启systemctl is-enable name.service
列出失败的服务systemctl --fail --type=service
开机启动并立即启动systemctl enable --now name.service
开机禁用并立即禁用systemctl disable --now name.service
查看服务依赖systemctl list-dependencies name.service
杀进程systemctl kill unitname

service unit 文件格式

[root@ubuntu ~]# apt install nginx
[root@ubuntu ~]# systemctl cat nginx.service 
# /lib/systemd/system/nginx.service
# Stop dance for nginx
# =======================
#
# ExecStop sends SIGSTOP (graceful stop) to the nginx process.
# If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control
# and sends SIGTERM (fast shutdown) to the main process.
# After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends
# SIGKILL to all the remaining processes in the process group (KillMode=mixed).
#
# nginx signals reference doc:
# http://nginx.org/en/docs/control.html
#

[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile
/run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

unit 文件格式说明

  • 以 # 开头的行后面的内容会被认为是注释

  • 相关布尔值 1,yes,on,true 等可以表示开启,0,no,off,false 等都可以表示关闭

  • 时间单位默认是秒,如果要使用其它时间单位,毫秒(ms),分钟(m) 等须显式说明

service unit file文件通常由三部分组成

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

[Unit] 字段中的常用选项

字段作用
Description描述信息
Documentation帮助信息
After定义unit的启动次序,表示当前unit应该晚于哪些unit启动,其功能与Before 相反
Before定义unit的启动次序,表示当前unit应该早于哪些unit启动,其功能与After相 反
Requires依赖到的其它units,强依赖,被依赖的units无法激活时,当前unit也无法激 活
Wants依赖到的其它units,弱依赖
Conflicts定义units间的冲突关系

[Service] 字段中的常用选项

字段说明
Type定义影响ExecStart及相关参数的功能的unit进程启动类型
EnvironmentFile环境配置文件
PIDFile指明生成进程文件路径
ExecStartPreExecStart前运行,可以有多条
ExecStart指明启动unit要运行命令或脚本的绝对路径
ExecStartPostExecStart后运行,可以有多条
ExecReload指明重新加载unit 配置要运行的命令或脚本
ExecStop指明停止unit要运行的命令或脚本
KillSignal以何信号杀死进程,默认SIGTERM
KillMode以何种方式杀死进程control-group
TimeoutStopSec在超过此时间后,如果进程没有被杀死,则继续使用SIGKILL配置或 FinalKillSignal配置停止进程
PrivateTmp布尔值,true 表示会生成私有的tmp目录,路径是/tmp/systemd-privateUUID-NAME.service-XXXXX/tmp/
Restart当守护进程意外终止时,是否自动重启
RestartSec意外终止到自动重启之间的时间间隔,其目的是保证前面的程序彻底退出, 默认值100ms

Type字段常用值

simple 		#默认值, 这个daemon主要由ExecStart接的指令串来启动,启动后常驻于内存中
forking 	#由ExecStart启动的程序透过spawns延伸出其他子程序来作为此daemon的主要服务, 原生父程序在启动结束后就会终止
oneshot 	#与simple类似, 不过这个程序在工作完毕后就结束了,不会常驻在内存中
dbus 		#与simple类似,但这个daemon必须要在取得一个D-Bus的名称后, 才会继续运作, 因此通常也要同时设定BusNname
notify 		#在启动完成后会发送一个通知消息, 还需要配合NotifyAccess来让Systemd 接收消息
idle 		#与simple类似, 要执行这个daemon必须要所有的工作都顺利执行完毕, 这类daemon通常是开机到最后才执行的服务

[Install] 字段中的常用选项

字段说明
Alias别名,可使用systemctl command Alias.service
WantedBy工作模式,就是在哪种运行级别下
Also安装本服务的时候还要安装别的相关服务

对于新创建的unit文件,或者修改了的unit文件,要通知systemd重载此配置文件,或者选择重启系统

systemctl daemon-reload
init q

运行级别

centOS7开始,使用 target 来定义运行级别

查看所有target

[root@ubuntu ~]# ll /usr/lib/systemd/system/*target
......
......
[root@ubuntu ~]# systemctl list-unit-files --type target --all
......
......

centOS7之后的 runlevel 不再定义在 /etc/inittab 文件中,且 ubuntu 中没有该文件

[root@rocky86 ~]# cat /etc/inittab 
# inittab is no longer used.
#
# ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# Ctrl-Alt-Delete is handled by /usr/lib/systemd/system/ctrl-alt-del.target
#
# systemd uses 'targets' instead of runlevels. By default, there are two main 
targets:
#
# multi-user.target: analogous to runlevel 3
# graphical.target: analogous to runlevel 5
#
# To view current default target, run:
# systemctl get-default
#
# To set a default target, run:
# systemctl set-default TARGET.target

查看默认启动级别

#相当于查看之前的 /etc/inittab
[root@rocky86 ~]# systemctl get-default
graphical.target
runlevel 和 target 之间的对应关系
运行级别target指向真实的文件
0runlevel0.targetpoweroff.target
1runlevel1.targetrescue.target
2runlevel2.targetmulti-user.target
3runlevel3.targetmulti-user.target
4runlevel4.targetmulti-user.target
5runlevel5.targetgraphical.target
6runlevel6.targetreboot.target
#重启对应的target
/usr/lib/systemd/system/ctrl-alt-del.target -> reboot.target

#默认target
/usr/lib/systemd/system/default.target -> graphical.target

查看当前运行级别

[root@ubuntu ~]# runlevel
N 5
[root@ubuntu ~]# who -r
         run-level 5  2022-09-03 11:21

运行级别切换

#重启, 相录于 init 6
[root@ubuntu ~]# systemctl isolate reboot.target
#同样支持
[root@ubuntu ~]# init 6 
#进入默认target
[root@ubuntu ~]# systemctl default

注意:只有/lib/systemd/system/*.target文件中AllowIsolate=yes 才能切换(修改文件需执行systemctl daemon-reload才能生效)

常用模式快捷切换

传统命令init,poweroff,halt,reboot都成为systemctl的软链接

rescue.target 比emergency.target 支持更多的功能,例如日志等

#切换至救援模式
systemctl rescue
#切换至紧急模式
systemctl emergency
#关机
systemctl halt
systemctl poweroff
#重启
systemctl reboot
#挂起
systemctl suspend
#休眠
systemctl hibernate
#休眠并挂起
systemctl hybrid-sleep

CentOS 7之后版本引导顺序

  1. UEFi或BIOS初始化,运行POST开机自检

  2. 选择启动设备

  3. 引导装载程序, centos7是grub2,加载装载程序的配置文件: /etc/grub.d/, /etc/default/grub ,/boot/grub2/grub.cfg

  4. 加载initramfs驱动模块(可以实现根文件系统的挂载)

  5. 加载虚拟根中的内核

  6. 虚拟根的内核初始化,Centos7使用systemd代替init,第一个进程

  7. 执行initrd.target 所有单元,包括挂载 /etc/fstab

  8. 从initramfs根文件系统切换到磁盘根目录

  9. systemd执行默认target配置,配置文件/etc/systemd/system/default.target

  10. systemd执行sysinit.target初始化系统及basic.target准备操作系统

  11. systemd启动multi-user.target 下的本机与服务器服务

  12. systemd执行multi-user.target 下的/etc/rc.d/rc.local

  13. Systemd执行multi-user.target下的getty.target及登录服务

  14. systemd执行graphical需要的服务

从 RHEL 9.1 开始,如果 RHEL 是唯一安装的操作系统,并且之前的引导成功,则 GRUB 引导装载程序 被配置为默认隐藏引导菜单

要访问引导菜单:

  • 在启动系统后,重复按 Esc 键

  • 引导系统后,重复按 F8

  • 在启动过程中按住 Shift

要禁用这个功能并配置引导装载程序菜单默认显示

grub2-editenv - unset menu_auto_hide

破解 root 密码

破解CentOS8,7的root密码

方法一

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

方法二

#此方式也适用于ubuntu18.04
启动时任意键暂停启动
按e键进入编辑模式
将光标移动linux 开始的行,添加 rw init=/sysroot/bin/sh
按ctrl+x启动
chroot /sysroot
passwd root
#如果SELinux是启用的,才需要执行下面操作,如查没有启动,不需要执行
touch /.autorelabel
exit
reboot

方法三

#ubuntu中显示 grub 菜单,同上
/etc/default/grub[root@ubuntu ~]# cat /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=timeout #改成 timeout
GRUB_TIMEOUT=10 #大于0
[root@ubuntu ~]# update-grub

grub2 安全

#添加grub2密码,会生在一个配置文件
[root@rocky86 ~]# ll /boot/grub2/user.cfg
ls: cannot access '/boot/grub2/user.cfg': No such file or directory
[root@rocky86 ~]# grub2-setpassword 
Enter password: 
Confirm password: 
[root@rocky86 ~]# ll /boot/grub2/user.cfg
-rw------- 1 root root 298 Sep  3 14:56 /boot/grub2/user.cfg

#清空grub2密码
[root@rocky86 ~]# cat /dev/null > /boot/grub2/user.cfg

#或者直接删除文件
[root@rocky86 ~]# rm -f /boot/grub2/user.cfg
[root@ubuntu ~]# grub-mkpasswd-pbkdf2 
Enter password: 
Reenter password: 
PBKDF2 hash of your password is 
grub.pbkdf2.sha512.10000.DE4B1993A5CB6504E9DA91746673413CD4C3B3FD390FDD4001EAD67
2DE281448CF2AF64000B95C378D7948E2243771A45E10E1B99FF879C4F8F08EDDA25C5536.331999
A3DFD5ECF205440CBBC48B2B1A2F4D08BB8731FA00E03ADBA990C228AD4D3D5D515EAED2350B20DB
F74810700A2E0003FAEF3E5F25D24E877385A3714F

#修改此文件,将上述生成的内容追加到该文件最后
[root@ubuntu ~]# vim /etc/grub.d/40_custom

set superusers="tom"
password_pbkdf2 tom 
grub.pbkdf2.sha512.10000.DE4B1993A5CB6504E9DA91746673413CD4C3B3FD390FDD4001EAD67
2DE281448CF2AF64000B95C378D7948E2243771A45E10E1B99FF879C4F8F08EDDA25C5536.331999
A3DFD5ECF205440CBBC48B2B1A2F4D08BB8731FA00E03ADBA990C228AD4D3D5D515EAED2350B20DB
F74810700A2E0003FAEF3E5F25D24E877385A3714F

#更新
[root@ubuntu ~]# update-grub

#重启,下次再选择grub,要输入用户名和密码

grub2 修复

grub2修复本质上来讲,跟grub修复同理

第1阶段或第1.5阶段,二进制数据损失,重装 grub2 即可

grub2-install /dev/sda #BIOS环境
grub2-install #UEFI环境

第二阶段 /boot/ 目录下文件丢失,则要重装内核,重装grub2,并重新生成配置文件

#删除/boot/下所有内容
[root@rocky86 ~]# rm -rf /boot/*
[root@rocky86 ~]# ls /boot/

#重启,从光盘启动,进救援模式

#切根
chroot /mnt/sysimage #centos7
chroot /mnt/sysroot     #centos8

#安装grub2
grub2-install /dev/sda #BIOS环境
grub2-install #UEFI环境

#挂载光盘
mount /dev/sr0 /mnt

#安装内核
rpm –ivh /mnt/Packages/kernel-3.10.0-1062.el7.x86_64.rpm --force 
#centos7
rpm -ivh /mnt/BaseOS/Packages/k/kernel-core-4.18.0-372.9.1.el8.x86_64.rpm --force #centos8

#生成配置文件
grub2-mkconfig -o /boot/grub2/grub.cfg

#重启
exit
reboot

内核参数管理

sysctl 命令用来配置linux 系统内核参数,这些参数以文件的形式显示在 /proc/sys/ 目录中, 配置项就是目录名加文件名,值就是该文件中的内容

注意:不是所有内核参数都是可以被修改的

查看所有配置项

#内核参数配置目录
[root@ubuntu ~]# ll /proc/sys
total 0
dr-xr-xr-x   1 root root 0 May 21 08:42 ./
dr-xr-xr-x 294 root root 0 May 21 08:42 ../
dr-xr-xr-x   1 root root 0 May 21 08:48 abi/
dr-xr-xr-x   1 root root 0 May 21 08:48 debug/
dr-xr-xr-x   1 root root 0 May 21 08:48 dev/
dr-xr-xr-x   1 root root 0 May 21 08:43 fs/
dr-xr-xr-x   1 root root 0 May 21 08:42 kernel/
dr-xr-xr-x   1 root root 0 May 21 08:43 net/
dr-xr-xr-x   1 root root 0 May 21 08:48 sunrpc/
dr-xr-xr-x   1 root root 0 May 21 08:48 user/
dr-xr-xr-x   1 root root 0 May 21 08:43 vm/

sysctl 格式

sysctl [options] [variable[=value] ...]

#常用选项
-a|-A|-x|--all #显示所有内核参数
-p|--load #重载
-N|--names #仅显示参数名称
-n|--values #仅显示参数值
-w|--write #设置内核参数

可用的配置文件

系统在启动时,会按下列顺序加载配置文件,读取参数值

/run/sysctl.d/*.conf  
/etc/sysctl.d/*.conf
/usr/local/lib/sysctl.d/*.conf 
/usr/lib/sysctl.d/*.conf 
/lib/sysctl.d/*.conf
/etc/sysctl.conf

常用内核参数

net.ipv4.ip_forward #是否开启ipv4地址转发
net.ipv4.icmp_echo_ignore_all #是否禁用ping功能
net.ipv4.ip_nonlocal_bind   #允许应用程序可以监听本地不存在的IP
vm.drop_caches #缓存回收机制 3 回收所有 2 释放数据区和信息节点

1 释放页面缓存
fs.file-max = 1020000 #内核可以支持的全局打开文件的最大数
vm.overcommit_memory = 0 #超分 0表示进程申请内存时会判断,不够则返回错误,1表示内核允许分配所有的物理内存,而不管当前的内存状态如何,2表示内核允许分配超过所有物理内存和交换空间总和的内存
vm.swappiness = 10           #使用swap空间时物量内存还有多少可用,10 表示物理存只有10%时才使用swap

#禁用IPv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

对于网络接口的配置,则会在对应的网络接口出现的时候才会生效,具体来说就是 net.ipv4.conf, net.ipv6.conf,net.ipv4.neigh, net.ipv6.neigh 等参数。

有部份sysctl 参数仅在加载了相应的内核模块之后才可用,因为内核模块是按需动态加载的(例如加入了 新的硬件或启动网络时),所以在 sysctl.conf 文件中无法设置的那些依赖于特定模块的参数。

  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值