Linux 的服务管理,就是玩一玩 systemctl 这个指令!还有开机流程的管理,也就是 grub2 啰!
之前的课程介绍过 process 与 program 的差别,也谈过 PID 信息的观察,以及包括 job control 等与进程相关的数据。 本节课会继续介绍 process 管理所需要具备的 signal 信息。另外,管理员是需要管理服务的,每个服务都是需要被启动的 process。 最终会介绍开机流程到底是如何运作。
服务就是一个被启动的进程,这个进程可以常驻于内存当中提供网络连接、例行工作调度等任务,就可称为服务。
一个程序被运行触发之后会变成在内存当中的一个活动的单位,那就是进程 (process)。之前的课程介绍过 PID 与进程的观察, 本小节会继续介绍 PID 的管理方面的任务。
管理员可以通过给某进程一个信号 (signal) 去告知该进程你想要让它作什么。主要的进程信号可以使用 kill -l 或 man 7 signal 查找, 底下截取较常见的信号代号与对应内容:
至于传输 signal 则是通过 kill 这个指令。举例来说,若管理员想要直接让前一堂课介绍的 rsyslogd 这个进程重读其设置档, 而不通过服务管理的正常机制时,可以尝试如下处理方式:
[root@localhost ~]# pstree -p | grep rsyslog |-rsyslogd(1769)-+-{rsyslogd}(1778) | |-{rsyslogd}(1779) | `-{rsyslogd}(1781) [root@localhost ~]# kill -1 1769 [root@localhost ~]# rjournalctl -u rsyslog [root@localhost ~]# tail /var/log/messages ...... May 26 17:14:00 station200 rsyslogd[1769]: [origin software="rsyslogd" swVersion="8.37.0-13.el8" x-pid="1769" x-info="http://www.rsyslog.com"] rsyslogd was HUPed
读者可以发现在注册表出现了 rsyslogd 被要求重新读取设置档的记录 (HUPed)!而除了 PID 之外,管理员也能够使用指令名称来给予 signal, 直接通过 killall 即可。如下管理方式:
[root@localhost ~]# killall -1 rsyslogd
从 CentOS 7 以后,Red Hat 系列的 distribution 放弃沿用多年的 System V 开机启动服务的流程, 改用 systemd 这个启动服务管理机制~采用 systemd 的原因如下:
但是 systemd 也有许多存在的问题:
基本上, systemd 将过去所谓的 daemon 运行脚本通通称为一个服务单位 (unit),而每种服务单位依据功能来区分时,就分类为不同的类型 (type)。 基本的类型有包括系统服务、数据监听与交换的插槽档服务 (socket)、保存系统状态的快照类型、提供不同类似运行等级分类的操作环境 (target) 等等。 至于设置档都放置在底下的目录中:
也就是说,到底系统开机会不会运行某些服务其实是看 /etc/systemd/system/ 底下的设置,所以该目录底下就是一大堆链接档。而实际运行的 systemd 启动脚本设置档, 其实都是放置在 /usr/lib/systemd/system/ 底下的!
/usr/lib/systemd/system/ 内的数据主要使用扩展名来进行分类,底下尝试找出 cron 与 multi-user 这些服务的数据:
[root@localhost ~]# ll /usr/lib/systemd/system/ | egrep 'multi-user|cron' -rw-r--r--. 1 root root 356 11月 9 2019 crond.service -rw-r--r--. 1 root root 532 6月 22 2018 multi-user.target drwxr-xr-x. 2 root root 258 5月 25 21:28 multi-user.target.wants lrwxrwxrwx. 1 root root 17 4月 10 05:52 runlevel2.target -> multi-user.target lrwxrwxrwx. 1 root root 17 4月 10 05:52 runlevel3.target -> multi-user.target lrwxrwxrwx. 1 root root 17 4月 10 05:52 runlevel4.target -> multi-user.target
所以我们可以知道 crond 其实算是系统服务 (service),而 multi-user 要算是运行环境相关的类型 (target type)。根据这些扩展名的类型, 我们大概可以找到几种比较常见的 systemd 的服务类型如下:
扩展名 | 主要服务功能 |
.service | 一般服务类型 (service unit):主要是系统服务,包括服务器本身所需要的本机服务以及网络服务都是!比较经常被使用到的服务大多是这种类型! |
.socket | 内部进程数据交换的插槽服务 (socket unit): 这种类型的服务通常在监控消息传递的插槽档,当有通过此插槽档传递消息来说要链接服务时,就依据当时的状态将该用户的要求发送到对应的 daemon, 若 daemon 尚未启动,则启动该 daemon 后再发送用户的要求。 使用 socket 类型的服务一般是比较不会被用到的服务,因此在开机时通常会稍微延迟启动的时间。一般用于本机服务比较多, 例如我们的图形界面很多的软件都是通过 socket 来进行本机进程数据交换的行为。 |
.target | 运行环境类型 (target unit):其实是一群 unit 的集合,例如上面表格中谈到的 multi-user.target 其实就是一堆服务的集合~也就是说, 选择运行 multi-user.target 就是运行一堆其他 .service 或/及 .socket 之类的服务就是了! |
其中又以 .service 的系统服务类型最常见。
一般来说,服务的启动有两个阶段,一个是『开机的时候设置要不要启动这个服务』, 以及『现在要不要启动这个服务』两个阶段。 这两个阶段都可以使用 systemctl 指令来管理。systemctl 的基本语法为:
[root@localhost ~]# systemctl [command] [unit]
上表所谓的 command 主要有:
缺省的情况下, systemctl 可以列出目前系统已经启动的服务群,如下列表:
[root@localhost ~]# systemctl
UNIT LOAD ACTIVE SUB DESCRIPTION
.....
proc-sys-fs-binfmt_misc.automount loaded active waiting Arbitrary Executable File>
sys-devices-pci0000:00-0000:00:01.1-ata2-host1-target1:0:0-1:0:0:0-block-sr0.device loade>
sys-devices-pci0000:00-0000:00:03.0-virtio0-net-ens3.device loaded active plugged Virti>
chronyd.service loaded active running NTP client/server
colord.service loaded active running Manage, Install and Gener>
crond.service loaded active running Command Scheduler
firewalld.service loaded active running firewalld - dynamic firew>
ModemManager.service loaded active running Modem Manager
graphical.target loaded active active Graphical Interface
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
170 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
列表当中,LOAD/ACTIVE/DESCRIPTION 等意义为:
如上表显示 chronyd 为 service 的类别,下次开机会启动 (load),而现在的状态是运作中 (active running)。最底下两行显示共有 170 的 unit 显示在上面, 如果想要列出系统上还没有被列出的服务群,可以加上 --all 来继续观察。此外,我们也能够仅针对 service 的类别来观察,如下所示:
[root@localhost ~]# systemctl list-units --type=service --all
如果想要观察更详细的每个启动的数据,可以通过底下的方式来处理:
[root@localhost ~]# systemctl list-unit-files
UNIT FILE STATE
proc-sys-fs-binfmt_misc.automount static
.......
atd.service enabled
crond.service enabled
.......
unbound-anchor.timer enabled
416 unit files listed.
Linux 缺省的操作画面可以是纯文本也能够是文本加上图形界面。早期的 systemV 系统称文本界面为 runlevel 3 而图形界面为 runlevel 5。 systemd 提供多种的操作界面,主要是通过『 target 』这种 unit 来作为规范。读者可以使用如下的指令来观察所有的 target:
[root@localhost ~]# systemctl list-units --type=target --all
在 CentOS 8 底下常见的操作界面 (target unit) 有底下几种:
而上述的操作模式中,缺省的是 multi-user 与 graphical 这两种。其实这些模式彼此之间还是有相依性的,读者可以使用如下的方式查出来 graphical 运行前, 有哪些 target 需要被运行:
[root@localhost ~]# systemctl list-dependencies graphical.target
graphical.target
● ├─.......
● └─multi-user.target
● ├─.......
● ├─basic.target
● │ ├─.......
● │ ├─sockets.target
● │ │ └─.......
● │ ├─sysinit.target
● │ │ ├─.......
● │ │ ├─local-fs.target
● │ │ │ └─.......
● │ │ └─swap.target
● │ │ └─.......
● │ └─timers.target
● │ └─.......
● ├─getty.target
● │ └─.......
● ├─nfs-client.target
● │ └─.......
● └─remote-fs.target
● └─nfs-client.target
● └─.......
上述的表格已经精简化过,仅保留了 unit=target 的项目,从里面读者也能够发现到要运行 graphical 之前,还得需要其他的 target 才行。 若须取得目前的操作界面,可以使用如下的方式来处理:
[root@localhost ~]# systemctl get-default
graphical.target
若需要设置缺省的操作界面,例如将原本的图形界面改为文本界面的操作方式时,可以使用如下的方式来处理:
[root@localhost ~]# systemctl set-default multi-user.target Removed /etc/systemd/system/default.target. Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/multi-user.target. [root@localhost ~]# systemctl get-default multi-user.target
如此即可将文本界面设置为缺省的操作环境。上述的作法是开机时才进行的缺省操作环境界面,若需要即时将图形界面改为文本界面, 或者反过来处理时,可以使用如下的方式来处置:
[root@localhost ~]# systemctl isolate multi-user.target
如果是网络服务,一般都会启动监听界面在 TCP 或 UDP 的封包端口口上。取得目前监听的端口口可以使用如下的方式:
[root@localhost ~]# netstat -tlunp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5355 0.0.0.0:* LISTEN 3076/systemd-resolv
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd
tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN 2136/dnsmasq
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 2390/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2765/master
tcp6 0 0 :::5355 :::* LISTEN 3076/systemd-resolv
tcp6 0 0 :::111 :::* LISTEN 1/systemd
tcp6 0 0 :::22 :::* LISTEN 2390/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2765/master
udp 0 0 0.0.0.0:50055 0.0.0.0:* 2247/avahi-daemon:
udp 0 0 127.0.0.53:53 0.0.0.0:* 3076/systemd-resolv
udp 0 0 192.168.122.1:53 0.0.0.0:* 2136/dnsmasq
udp 0 0 0.0.0.0:67 0.0.0.0:* 2136/dnsmasq
udp 0 0 0.0.0.0:35930 0.0.0.0:* 3082/rsyslogd
udp 0 0 0.0.0.0:111 0.0.0.0:* 1/systemd
udp 0 0 0.0.0.0:5353 0.0.0.0:* 2247/avahi-daemon:
udp 0 0 0.0.0.0:5355 0.0.0.0:* 3076/systemd-resolv
udp 0 0 127.0.0.1:323 0.0.0.0:* 2262/chronyd
udp 0 0 0.0.0.0:514 0.0.0.0:* 3082/rsyslogd
udp6 0 0 :::111 :::* 1/systemd
udp6 0 0 :::5353 :::* 2247/avahi-daemon:
udp6 0 0 :::5355 :::* 3076/systemd-resolv
udp6 0 0 :::57581 :::* 2247/avahi-daemon:
udp6 0 0 ::1:323 :::* 2262/chronyd
udp6 0 0 :::514 :::* 3082/rsyslogd
重点在 Local Address 那一行,会显示该服务是启动在本机的哪一个 IP 界面的哪一个端口口上,如此管理员即可了解启动该端口口的服务是哪一个。 若无须该网络服务,则可以将该进程关闭。以上述表格来说,如果需要关闭 avahi-daemon, systemd-resolv 时,可以使用如下的方式取得服务名称:
[root@localhost ~]# systemctl list-unit-files | egrep 'avahi|systemd-resolv'
avahi-daemon.service enabled
systemd-resolved.service enabled
avahi-daemon.socket enabled
若需要将其关闭,则应该使用如下的方式,将『目前』与『缺省』的服务启动都关闭才行:
[root@localhost ~]# systemctl stop avahi-daemon.service systemd-resolved.service avahi-daemon.socket [root@localhost ~]# systemctl disable avahi-daemon.service systemd-resolved.service avahi-daemon.socket [root@localhost ~]# netstat -tlunp
读者将可发现到 avahi-daemon 以及 systemd-resolv 的服务已经被关闭。而若需要启动某个网络服务,则需要了解到该服务是由哪一个软件所启动的, 该软件需要先安装后才可以启动该服务。比较特别的是 dnsmasq 这个服务,事实上,这个服务是被虚拟化系统所唤醒使用的,所以, 要关闭这个服务,得要关闭虚拟化数据才行。
[root@localhost ~]# systemctl status libvirtd ● libvirtd.service - Virtualization daemon Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2020-05-26 23:08:27 CST; 8min ago Docs: man:libvirtd(8) https://libvirt.org Main PID: 2391 (libvirtd) ..... # 确实活着喔! [root@localhost ~]# virsh list Id 名称 状态 ----------------------------------------------------
[root@localhost ~]# virsh net-list
名称 状态 自动启动 Persistent
----------------------------------------------------------
default 激活 yes yes
[root@localhost ~]# virsh net-destroy default [root@localhost ~]# virsh net-undefine default
[root@localhost ~]# netstat -tlunp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 2390/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2765/master
tcp6 0 0 :::111 :::* LISTEN 1/systemd
tcp6 0 0 :::22 :::* LISTEN 2390/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2765/master
udp 0 0 0.0.0.0:35930 0.0.0.0:* 3082/rsyslogd
udp 0 0 0.0.0.0:111 0.0.0.0:* 1/systemd
udp 0 0 127.0.0.1:323 0.0.0.0:* 2262/chronyd
udp 0 0 0.0.0.0:514 0.0.0.0:* 3082/rsyslogd
udp6 0 0 :::111 :::* 1/systemd
udp6 0 0 ::1:323 :::* 2262/chronyd
udp6 0 0 :::514 :::* 3082/rsyslogd
上面这几个服务大概就是一台正常的 Linux 系统应该要具有的服务,所以,不要在随便关闭喔!
因为每个 Server 的使用情境不同,有的在虚拟机当中,有的是实体机,有的需要使用一般网络服务功能,有的要加强本身网络传输, 有的则是需要进行科学运算等等。也因为不同的设计参考依据不一样,因此缺省的系统参数可能就不会相当适合于你的环境。
以前要调整 (tune) 系统性能时,需要进行一大堆的设置,包括内核模块、内核参数、网络参数、磁盘参数等等,相当复杂。 现在的系统则加入了名为 tuned 这个服务,通过这个服务的动态处理,可以随时以你选定的环境 (profile) 来统一处理性能优化的相关问题, 而无须每项事情都要管理员去处理了!
tuned 这个服务缺省提供了许多的环境让你选择优化的情境,要查阅可以使用底下的方式处理:
[root@localhost ~]# tuned-adm list Available profiles: - balanced - General non-specialized tuned profile - desktop - Optimize for the desktop use-case - hpc-compute - Optimize for HPC compute workloads - latency-performance - Optimize for deterministic performance at the cost of increased power consumption - network-latency - Optimize for deterministic performance at the cost of increased power consumption, focused on low latency network performance - network-throughput - Optimize for streaming network throughput, generally only necessary on older CPUs or 40G+ networks - powersave - Optimize for low power consumption - throughput-performance - Broadly applicable tuning that provides excellent performance across a variety of common server workloads - virtual-guest - Optimize for running inside a virtual guest - virtual-host - Optimize for running KVM guests Current active profile: virtual-guest
一般来说,如果是实体机器且没有激活虚拟化功能的话,建议使用『 throughput-performance 』即可,一般用来当测试机或桌机的话,选择 『 desktop 』应该是不错的,如果是用来跑科学计算,或许也能使用『 hpc-compute 』,只是用来作为 IoT 的数据收集用服务器, 使用『 powersave 』应该也可以。如果是在虚拟机里面,但是有需要用到网络功能,想要降低延迟的话 (代价就是整体带宽使用率会较低), 或许也能使用『 network-latency 』。总之,要依据你的使用情境而挑选。
为了避免麻烦,其实 tuned-adm 也会自己分析你的系统所处环境,然后给予适当的建议!你就可以依据该建议来设计你的环境优化。
当然这个建议或许不是很适合你,只是单纯依据当下的系统而给的建议而已喔!以鸟哥的科学计算环境来说,该环境底下经常会有大量网络传输的需求, 并且需要的并不是带宽 (因为带宽已经达到 10G 了),而是反应速度。此时,该环境比较适合的情境或许要选择『network-latency』才对! 但是一般这样的实体机器系统,tuned 会建议使用 throughput-performance。然而鸟哥的经验中, throughput-performance 确实是当中性能最高的! 不过,如果不是单独本机运作的软件,需要跨足到其他台主机协同运作时,经常会有网络延迟的问题啊!
[root@localhost ~]# tuned-adm recommend
virtual-guest
看起来是建议使用 virtual-guest 的环境,因为教材的系统就是使用虚拟化,所以这个建议应该是没问题的![root@localhost ~]# tuned-adm profile virtual-guest [root@localhost ~]# tuned-adm active Current active profile: virtual-guest这样应该就已经设置好我们的环境了!
[root@localhost ~]# tuned-adm verify
Verification failed, current system settings differ from the preset profile.
You can mostly fix this by restarting the Tuned daemon, e.g.:
systemctl restart tuned
or
service tuned restart
Sometimes (if some plugins like bootloader are used) a reboot may be required.
See tuned log file ('/var/log/tuned/tuned.log') for details.
有些时候设计完毕后, tuned 可能没有办法直接处理,这时可以依据上述的注册表内容,查找一下可能的问题。
虚拟机会失败的原因,是因为虚拟机不能改 CPU 的运作模式,该模式必需要实体机器去设置才行。
要确认你的系统是否能够支持 CPU 的修改,可以使用底下的方式来处理:
[root@localhost ~]# cpupower frequency-info analyzing CPU 0: no or unknown cpufreq driver is active on this CPU CPUs which run at the same hardware frequency: Not Available CPUs which need to have their frequency coordinated by software: Not Available maximum transition latency: Cannot determine or is not supported. Not Available available cpufreq governors: Not Available Unable to determine current policy current CPU frequency: Unable to call hardware current CPU frequency: Unable to call to kernel boost state support: Supported: no Active: no正常的情境下,上面表格中的 cpufreq governors 会告诉你可用的 CPU 环境设计,这里并不行啊!这是因为虚拟机的影响所致。 所以,上面的检测错误是可以被忽略的!
系统如果出错,可能需要进入救援模式才能够处理相关的任务。但如何进入救援模式?这就需要从开机流程分析来下手。
一般正常的情况下, Linux 的开机流程会是如下所示:
如上,读者们可以发现内核文件驱动系统完成后,接下来就是 systemd 的任务,也就是前一小节所探讨的内容。但内核文件在哪里? 以及如何设置不同的内核文件开机,那就是开机管理程序的任务了。
系统的内核大多放置于 /boot/vmlinuz* 开头的文件中,而 initramfs 则放置于 /boot/initramfs* 。 至于内核的模块则放置于 /lib/modules/$(uname -r)/ 目录内。
目前系统上面已经加载的模块,可以使用底下的方式来观察:
[root@localhost ~]# lsmod [root@localhost ~]# lsmod | egrep 'Module|xfs' Module Size Used by xfs 1474560 2 libcrc32c 16384 3 nf_conntrack,nf_nat,xfs
如上所示,xfs 为独立运作的模块,不过还是被 2 个其他进程所使用 (Used by)!如果你使用 df -T | grep xfs 去查阅一下, 就会知道目前系统应该有两个设备就是使用 xfs 文件系统挂载的情境。另外,这个 xfs 模块会去使用到 libcrc32c 这个模块的意思! 也就是说,其实,模块也是有相依性的喔!
至于,若找到名为 xfs 的模块后,要想了解该模块的功能,可以使用如下的方式查找:
[root@localhost ~]# modinfo xfs
filename: /lib/modules/4.18.0-147.8.1.el8_1.x86_64/kernel/fs/xfs/xfs.ko.xz
license: GPL
description: SGI XFS with ACLs, security attributes, no debug enabled
author: Silicon Graphics, Inc.
alias: fs-xfs
rhelversion: 8.1
srcversion: 6EB85FD6AC0E0ED926C6D92
depends: libcrc32c
intree: Y
name: xfs
vermagic: 4.18.0-147.8.1.el8_1.x86_64 SMP mod_unload modversions
sig_id: PKCS#7
signer: CentOS Linux kernel signing key
sig_key: 57:35:0B:1E:DC:CE:14:72:7C:A0:26:12:B2:7B:38:69:93:62:B5:22
sig_hashalgo: sha256
signature: 4B:ED:60:E8:55:5D:A1:67:0A:56:A8:74:89:1B:C0:92:CE:A1:09:2A:
.....
若想要加载某个模块,就使用 modprobe 来加载,卸载则使用 modprobe -r 来卸载即可。
某些情况下,你会需要更动内核参数。而缺省的内核参数字于 /proc/sys/ 底下。一般不建议用户直接使用手动修改方式处理 /proc 内的文件 (因为下次开机就不会持续提供),应使用修改 /etc/sysctl.conf 来处理。举例而言,若你的 server 不想要回应 ping 的封包, 则可以如此测试:
[root@localhost ~]# ping -c 2 localhost4 PING localhost (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.044 ms 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.047 ms --- localhost ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 30ms rtt min/avg/max/mdev = 0.044/0.045/0.047/0.006 ms [root@localhost ~]# echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all [root@localhost ~]# ping -c 2 localhost4 PING localhost (127.0.0.1) 56(84) bytes of data. --- localhost ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 31ms [root@localhost ~]# echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
读者可以发现 icmp 确实不会回应 ping 的要求了。而这个设置值如果一定要每次开机都生效, 可以写入 /etc/sysctl.d/*.conf 内,写法为:
[root@localhost ~]# vim /etc/sysctl.d/mycentos.conf net.ipv4.icmp_echo_ignore_all = 1 [root@localhost ~]# sysctl -p /etc/sysctl.d/mycentos.conf [root@localhost ~]# cat /proc/sys/net/ipv4/icmp_echo_ignore_all 1
如此则可以每次都生效了。不过,这个功能对于内部环境的测试还是很重要的,因此还是请修订回来比较妥当。
内核的加载与设置是由开机管理程序来处理的,而 CentOS 8 缺省的开机管理程序为 grub2 这一个软件。该软件的优点包括有:
开机时,数据得从磁盘读出,因此磁盘、分区的代号信息得先要了解厘清才行。 grub2 对磁盘的代号定义如下:
(hd0,1) # 一般的缺省语法,由 grub2 自动判断分割格式 (hd0,msdos1) # 此磁盘的分割为传统的 MBR 模式 (hd0,gpt1) # 此磁盘的分割为 GPT 模式
所以说,整个硬盘代号为:
硬盘搜索顺序 | 在 Grub2 当中的代号 |
第一颗(MBR) | (hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3).... |
第二颗(GPT) | (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3).... |
第三颗 | (hd2) (hd2,1) (hd2,2) (hd2,3).... |
基本上,开机时 grub2 会去读取的设置档就是 grub.cfg 这个文件,但是这个文件是由系统程序分析创建的,不建议读者们手动修改。 因此底下读者先观察该文件内容即可,先不要修订。
[root@localhost ~]# cat /boot/grub2/grub.cfg ### BEGIN /etc/grub.d/00_header ### set pager=1 if [ -f ${config_directory}/grubenv ]; then load_env -f ${config_directory}/grubenv elif [ -s $prefix/grubenv ]; then load_env fi ........ if [ x$feature_timeout_style = xy ] ; then set timeout_style=menu set timeout=5 # Fallback normal timeout code in case the timeout_style feature is # unavailable. else set timeout=5 fi ### END /etc/grub.d/00_header ### ....... ### BEGIN /etc/grub.d/10_linux ### insmod part_gpt insmod ext2 set root='hd0,gpt2' <==Linux 内核所在的分区 if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2' 73f13e7b-43c4-43c5-93b4-9e65b962752d # 上一列的 --set=root 则是指定具有这个 UUID 的文件系统为根目录 else search --no-floppy --fs-uuid --set=root 73f13e7b-43c4-43c5-93b4-9e65b962752d fi set default_kernelopts="root=/dev/mapper/centos-root ro crashkernel=auto quiet " # This section was generated by a script. Do not modify the generated file - all changes # will be lost the next time file is regenerated. Instead edit the BootLoaderSpec files. # # The blscfg command parses the BootLoaderSpec files stored in /boot/loader/entries and # populates the boot menu. Please refer to the Boot Loader Specification documentation # for the files format: https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/. insmod blscfg blscfg ### END /etc/grub.d/10_linux ### ....... ### BEGIN /etc/grub.d/41_custom ### if [ -f ${config_directory}/custom.cfg ]; then source ${config_directory}/custom.cfg elif [ -z "${config_directory}" -a -f $prefix/custom.cfg ]; then source $prefix/custom.cfg; fi ### END /etc/grub.d/41_custom ###
这个 grub.cfg 文件分为数个部份,分别由不同的设置档集成而来,上表中的特殊字体是比较重要的部份。至于比较重要的内容,大致说明如下:
在 10_linux 的阶段中,有两个主要的 root 设置,一个是设置内核所在处的『 set root='hd0,gpt2' 』,另一个则是设置根目录的所在文件系统, 也就是『 search --no-floppy --fs-uuid --set=root 』那一行!两个 root 的意义不相同喔!这点要特别留意!
上面谈到的 blscfg 当中,通过文档的说明,可以发现 blscfg 会去调用 /boot/loader/entries/ 里面的设置档,先来看看该目录有什么信息:
[root@localhost ~]# ls /boot/loader/entries/
502dbaaf2a074134909a59ef9ab651c1-0-rescue.conf
502dbaaf2a074134909a59ef9ab651c1-4.18.0-147.8.1.el8_1.x86_64.conf
502dbaaf2a074134909a59ef9ab651c1-4.18.0-147.el8.x86_64.conf
直接拿 4.18.0-147.el8.x86_64 这个文件内容来瞧瞧:
[root@localhost ~]# cat /boot/loader/entries/*-4.18.0-147.el8.x86_64.conf
title CentOS Linux (4.18.0-147.el8.x86_64) 8 (Core)
version 4.18.0-147.el8.x86_64
linux /vmlinuz-4.18.0-147.el8.x86_64
initrd /initramfs-4.18.0-147.el8.x86_64.img $tuned_initrd
options $kernelopts $tuned_params
id centos-20191204215851-4.18.0-147.el8.x86_64
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel
这个文件当中,比较重要的项目大概是:
基本上,修改 grub2 设置档你可以在如下的位置进行:
主要环境设置内容为:
[root@www ~]# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto resume=/dev/mapper/centos-swap rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
若有修改上述文件,则需要使用 grub2-mkconfig -o /boot/grub2/grub.cfg 来进行修订。现在假设:
那应该要如何处理 grub.cfg 呢?基本上,你应该要修订 /etc/default/grub 的内容如下:
[root@localhost ~]# vim /etc/default/grub GRUB_TIMEOUT=40 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto (..中间省略..) rhgb quiet intel_iommu=on" GRUB_DISABLE_RECOVERY="true" GRUB_ENABLE_BLSCFG=true
修改完毕之后再来则是进行输出修订的任务:
[root@localhost ~]# grub2-mkconfig -o /boot/grub2/grub.cfg Generating grub configuration file ... done [root@localhost ~]# reboot
若想要知道是否完整的变更了,请 vim /boot/grub2/grub.cfg 查阅相关设置值是否变更即可。重新开机后,你就可以发现菜单会等待到 40 秒喔!然后,重新开机完毕并登录系统, 查找一下内核参数是否正确的激活了:
[root@localhost ~]# cat /proc/cmdline BOOT_IMAGE=(hd0,gpt2)/vmlinuz-4.18.0-147.8.1.el8_1.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto resume=/dev/mapper/centos-swap rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet intel_iommu=on
grub2-mkconfig 运行之后会去分析 /etc/grub.d/* 里面的文件,然后运行该文件来建置 grub.cfg。至于 /etc/grub.d/ 目录底下会有这些文件存在:
所以,一般来说,我们会更动到的就是仅有 40_custom 这个文件即可。然而由于 CentOS 8 使用了 blscfg 的模块, 因此 Linux 相关的文件系统菜单,请自行到 /boot/loader/entries/ 去建置相关的设置即可。那如果需要额外的其他操作系统的菜单时, 才需要用到 40_custom 的内容喔!
在缺省的内核里面,你还需要有额外的菜单,例如你要创建一个一定进入图形界面与一个一定进入文本界面的菜单时, 就可以额外创建两个菜单文件!直接跑到 /boot/loader/entries/ 里头去处理即可!也不需要重新创建 grub.cfg 喔!相当简单:
[root@localhost ~]# cd /boot/loader/entries/ [root@localhost entries]# cp 502...-4.18.0-147.el8.x86_64.conf custom-graphical-4.18.0-147.el8.x86_64.conf [root@localhost entries]# cp 502...-4.18.0-147.el8.x86_64.conf custom-textmode-4.18.0-147.el8.x86_64.conf [root@localhost entries]# vim custom-graphical-4.18.0-147.el8.x86_64.conf title CentOS Linux (4.18.0-147.el8.x86_64) 8 (Core) - GUI Mode version 4.18.0-147.el8.x86_64 linux /vmlinuz-4.18.0-147.el8.x86_64 initrd /initramfs-4.18.0-147.el8.x86_64.img $tuned_initrd options $kernelopts $tuned_params systemd.unit=graphical.target id centos-20191204215851-4.18.0-147.el8.x86_64 grub_users $grub_users grub_arg --unrestricted grub_class kernel [root@localhost entries]# vim custom-textmode-4.18.0-147.el8.x86_64.conf title CentOS Linux (4.18.0-147.el8.x86_64) 8 (Core) - Text Mode version 4.18.0-147.el8.x86_64 linux /vmlinuz-4.18.0-147.el8.x86_64 initrd /initramfs-4.18.0-147.el8.x86_64.img $tuned_initrd options $kernelopts $tuned_params systemd.unit=multi-user.target id centos-20191204215851-4.18.0-147.el8.x86_64 grub_users $grub_users grub_arg --unrestricted grub_class kernel
[root@localhost ~]# cat /proc/cmdline
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-4.18.0-147.el8.x86_64 .... intel_iommu=on systemd.unit=multi-user.target
所谓的 chain loader (开机管理程序的链结) 仅是在将控制权交给下一个 boot loader 而已, 所以 grub2 并不需要认识与找出 kernel 的文件名 ,『 他只是将 boot 的控制权交给下一个 boot sector 或 MBR 内的 boot loader 而已 』 所以通常他也不需要去查验下一个 boot loader 的文件系统!
一般来说, chain loader 的设置只要两个就够了,一个是预计要前往的 boot sector 所在的分区代号, 另一个则是设置 chainloader 在那个分区的 boot sector (第一个磁区) 上!假设我的 Windows 分区在 /dev/sda1 ,且我又只有一颗硬盘,那么要 grub 将控制权交给 windows 的 loader 只要这样就够了:
menuentry "Windows" { insmod chain # 你得要先加载 chainloader 的模块对吧? insmod ntfs # 建议加入 windows 所在的文件系统模块较佳! set root=(hd0,1) # 是在哪一个分区~最重要的项目! chainloader +1 # 请去 boot sector 将 loader 软件读出来的意思! }
通过这个项目我们就可以让 grub2 交出控制权了!
[root@study ~]# fdisk -l /dev/vda
Device Boot Start End Blocks Id System
/dev/vda1 2048 10487807 5242880 83 Linux
/dev/vda2 * 10487808 178259967 83886080 7 HPFS/NTFS/exFAT
/dev/vda3 178259968 241174527 31457280 83 Linux
其中 /dev/vda2 使用是 windows 10 的操作系统。现在我需要增加两个开机选项,一个是取得 windows 10 的开机菜单,一个是回到 MBR 的缺省环境,应该如何处理呢?
[root@study ~]# vim /etc/grub.d/40_custom menuentry 'Go to Windows 10' --id 'win10' { insmod chain insmod ntfs set root=(hd0,msdos2) chainloader +1 } menuentry 'Go to MBR' --id 'mbr' { insmod chain set root=(hd0) chainloader +1 } [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg另外,如果每次都想要让 windows 变成缺省的开机选项,那么在 /etc/default/grub 当中设置好『 GRUB_DEFAULT=win10 』 然后再次 grub2-mkconfig 这样即可啦!不要去算 menuentry 的顺序喔!通过 --id 内容来处理即可!
不同的档系统允许安装 grub 的区块并不相同。XFS 文件系统似乎没有预留 boot sector 给 boot loader 使用, 因此 XFS 并不能安装独立的 boot loader。如果你想要让每个独立的 OS 都有自己的 boot sector,那么就得要使用 ext2 家族, 例如 ext4 才行!
至于 UEFI 的开机管理方式与 BIOS 并不相同,处理上就不能使用本章节的方式了!
一般来说,如果是文件系统错误,或者是某些开机过程中的问题,我们可以通过开机时进入 grub2 的交互界面中, 在 linux 的字段,加入 rd.break 或者是 init=/bin/bash 等方式来处理即可。但是,如果是 grub2 本身就有问题, 或者是根本就是内核错误,或者是 initramfs 出错时,那就无法通过上述的方式来处理了。
在 CentOS 7 的操作经验中,在升级内核时,偶而会有 initramfs 制作错误的情况导致新内核无法开机的问题。 此时,若你已经没有保留旧的内核,此时就无法顺利开机了。在 CentOS 8 里面倒是比较少出现这样的问题。
但若是发生这问题是,最常见的解决方法有两个:
如果是一开始安装就出事,那就得要通过底下的方案来处理了!下面是仿真进入光盘救援模式的方式:
sh4.2# touch /.autorelabel sh4.2# exit sh4.2# reboot
/proc/sys/vm/dirty_ratio 改成 40 /proc/sys/vm/dirty_background_ratio 改成 5 /proc/sys/vm/swappiness 改成 10且每次系统开机都会生效!
作业硬盘一般操作说明:
作业当中,某些部份可能为简答题~若为简答题时,请将答案写入 /home/student/ans.txt 当中,并写好正确题号,方便老师订正答案。 请注意,文件名写错将无法上传!
请使用 root 的身份进行如下实做的任务。直接在系统上面操作,操作成功即可,上传结果的程序会主动找到你的实做结果。
作业结果传输:请以 root 的身分运行 vbird_book_check_unit 指令上传作业结果。 正常运行完毕的结果应会出现【XXXXXX_aa:bb:cc:dd:ee:ff_unitNN】字样。若需要查阅自己上传数据的时间, 请在操作系统上面使用浏览器查找: http://192.168.251.254 检查相对应的课程文件。 相关流程请参考: vbird_book_check_unit