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