前提:pc主機,MBR架構 第一步:post(power on system test)加電自檢。 pc機的主板上有個rom晶元(CMOS),加電後,cpu去找這個raw,然後讀取裡面的指令,檢測機器上是否有:記憶體,硬碟,顯示設備等。 CMOS里有個bios(basic input output s ...
前提:pc主機,MBR架構
第一步:post(power on system test)加電自檢。
pc機的主板上有個rom晶元(CMOS),加電後,cpu去找這個raw,然後讀取裡面的指令,檢測機器上是否有:記憶體,硬碟,顯示設備等。
CMOS里有個bios(basic input output system)程式
第二步:boot sequence(bios里設置是用光碟啟動,還是硬碟啟動等)
按次序查找引導設備,第一個有引導程式(bootloader)的設備即為本次啟動要用到的設備。
bootloader:
功能:
- 找到磁碟上的grub程式,並載入運行之。
- grub提供一個可以讓用戶選擇的菜單,上面寫著,可以選擇運行的內核列表
- 把用戶選定的內核程式從磁碟載入到記憶體的特定空間中,然後解壓,展開,此後,內核就開始真正運行起來了,然後bootloader退出,由內核接管一切。
註意:由於bootloader僅有446位元組,它無法讀取LVM,軟RAID的邏輯分區,只能讀取物理分區,所以內核程式只能存放在物理分區上。
種類:
LILO:linux loader。它有個致命弱點,如果內核在磁碟的1024以後的柱面上存儲著的話,它無法載入內核。安卓手機用的是LILO。
GRUB:Grand Uniform Bootloader
centos5,6用的版本是:grub 0.x(別名:grub legacy)
cengtos7用的版本是:grub 1.x(別名:grub2)
bootloader程式放在哪裡了?
如果是MBR架構,則放在了在0號track(磁軌),0號sector(扇區)里 的前446bytes 。
由於只有446位元組,空間太小了,能寫的程式實在有限,所以linux使用GRUB機制。
GRUB機制:不讓bootloader直接載入內核,而是讓bootloader載入磁碟上的另外一個程式/boot/grub。由於/boot/grub是放在磁碟上的,所以突破了446位元組的約束。
第一階段:bootloader載入/boot/grub程式
第1.5階段:filesystem driver?
第二階段:
centos5,6:載入/boot/grub下的配置文件
centos7:載入/etc/grub.d/, /etc/default/grub, /boot/grub2/grub.cfg
# ll /etc/grub.d/ -rwxr-xr-x. 1 root root 8702 Nov 9 2018 00_header -rwxr-xr-x. 1 root root 1043 Jul 5 2018 00_tuned -rwxr-xr-x. 1 root root 232 Nov 9 2018 01_users -rwxr-xr-x. 1 root root 10781 Nov 9 2018 10_linux -rwxr-xr-x. 1 root root 10275 Nov 9 2018 20_linux_xen -rwxr-xr-x. 1 root root 2559 Nov 9 2018 20_ppc_terminfo -rwxr-xr-x. 1 root root 11169 Nov 9 2018 30_os-prober -rwxr-xr-x. 1 root root 214 Nov 9 2018 40_custom -rwxr-xr-x. 1 root root 216 Nov 9 2018 41_custom -rw-r--r--. 1 root root 483 Nov 9 2018 README # ll /etc/default/grub -rw-r--r--. 1 root root 279 Nov 29 16:53 /etc/default/grub # ll /boot/grub2/grub.cfg -rw-r--r--. 1 root root 4287 Nov 29 16:53 /boot/grub2/grub.cfg
第三步:kernel自身初始化
探測所以硬體設備
為了載入磁碟上的根文件系統,所以先載入ramdisk上的文件系統,找到裡面的磁碟驅動程式。
註意:也有可能不使用ramdisk。當自己在自己的機器上編譯內核時,編譯程式就探測到了本地磁碟類型,所以在編譯的時候,就可以把磁碟的驅動,編譯到內核里,所以內核就不需要再去找ramdisk了。
使用磁碟驅動,以只讀方式,載入根文件系統。只讀的目的:防止內核有bug,把根文件系統裡面的東西刪除了。沒問題後,再改為讀寫方式。
運行用戶空間的第一個應用程式:/sbin/init
centos5之前的init程式:SysV init
使用的配置文件:/etc/inittab
centos6的init程式:Upstart(ubuntu貢獻的,redhat參考ubuntu又修改了一下)
使用的配置文件:/etc/init/*.conf
centos7的init程式:Systemd(redhat參考macOS做的)
使用的配置文件: /usr/lib/systemd/system目錄下的文件,和/etc/systemd/system目錄下的文件
- 執行/usr/lib/systemd/system/initrd.target所有單元,掛載/etc/fstab里的分區
- 從ramdisk根文件系統切換到磁碟根目錄
- 執行/etc/systemd/system/default.target
- 執行/usr/lib/systemd/system/sysinit.target,及/usr/lib/systemd/system/basic.target
- systemd啟動/usr/lib/systemd/system/multi-user.target里的本機的服務和伺服器的服務
- systemd執行/usr/lib/systemd/system/multi-user.target里的/etc/rc.d/rc.local
- systemd執行/usr/lib/systemd/system/multi-user.target里的getty.target及登錄服務
- 如果命令
systemctl get-default
的執行結果是graphical,則執行/usr/lib/systemd/system/graphical.target
第四步:/sbin/init會啟動/sbin/mingetty程式,顯示可以登錄的文本界面。
Systemd的新特性:
- 並行啟動無依賴關係的服務
- 按需激活服務,不是全啟動起來,放在那裡浪費資源,用戶真正用的時候才啟動
- 可以提供用戶空間進程的快照
- 可以基於依賴關係定義服務控制邏輯
Systemd的核心概念:unit
unit是一個抽象的東西,它由其相關的配置文件進行標識,識別和配置。
配置文件中,主要包含了系統服務,監聽的socket,保存的快照,以及其他與init相關的信息。
查看有哪些unit file:
# systemctl list-unit-files -a
UNIT FILE STATE
proc-sys-fs-binfmt_misc.automount static
dev-hugepages.mount static
brandbot.path disabled
cups.path enabled
...
unit配置文件的放置目錄:
/usr/lib/systemd/system
每個服務最主要的啟動腳本設置,類似於centos5,6里的/ect/init.d/*.conf
/run/systemd/system/
系統執行過程中所產生的服務腳本,比上面目錄優先運行
/etc/systemd/system
管理員建立的執行腳本,類似於centos5,6里的/etc/rc.d/rc#.d/S##腳本的功能,比上面目錄優先運行。
unit的常見類型:
service:文件擴展名為service,用於定義系統服務的
相容cenos5,6的命令:
service NAME start|stop|status|restart
target:文件擴展名為target,模擬centos5,6里運行級別(rc0.d,rc1.d,rc2.d,rc3.d,rc4.d,rc5.d,rc6.d目錄 里的K*和S*的所有腳本 ).
centos7里沒有運行級別的概念,centos5,6是靠運行級別控制的。
device:文件擴展名為device,用於定義內核識別的設備
centos5,6的設備文件是由udev識別的,centos7的設備文件是由udev和systemd識別的。
mount:文件擴展名為mount,用於定義文件系統的掛載點
在centos7直接輸入mount命令,會發現很多cgroup的掛載點。cgroup是控制資源分配的,docker就是利用cgroup分配資源,用namespace隔離網路等空間。
socket:文件擴展名為socket,用於標識進程間通信所使用的socket文件。
snapshot:文件擴展名為snapshot,用於管理系統快照的
swap:文件擴展名為swap,用於管理swap設備
automount:文件擴展名為automount,文件系統自動掛載點設置。比如插入U盤,自動識別
path:文件擴展名為path,用於定義文件系統中的文件或目錄。
關鍵特性:
基於socket的激活機制:socket與程式分離。
只是啟動socket,來監聽埠,但程式並不啟動,當監聽到請求過來 了,則激活程式。
基於bus(匯流排)的激活機制,如果匯流排上存在對某個服務的訪問,則激活之
基於device(設別)的激活機制,當設備接入後,會自動激活mount,device,automount的unit,這些unit發現設備來了,則創建設備文件,並掛載,如果掛載點不存在,則自動創建掛載點。
基於path的激活機制。用例:當某個服務意外終止後,假如它會創建個文件或目。此path機制就是監視系統里是否生成了這個文件或目錄,如果有,則激活某個服務(告訴公司的人,你的服務掛了等)。
系統快照:保存各unit的當前狀態於持久設備設備存儲中。用於恢復unit到指定時間點。讓unit在過去和未來間游走。
向後相容sysv init腳本:放在/etc/init.d/下的腳本,也可以通過systemd激活。
不相容的:
- systemctl命令是固定不變的,不能像service那樣,隨意定義命令。
- 非由systemld啟動的服務,systemctl命令則無法與之通信,所以就無法管理之。
管理系統服務:service類型的unit負責管理服務的
systemctl - Control the systemd system and service manager
systemctl [OPTIONS...] COMMAND [NAME...]
COMMANDS
Unit Commands
list-units [PATTERN...]
list-sockets [PATTERN...]
list-timers [PATTERN...]
start PATTERN...
stop PATTERN...
restart PATTERN...
try-restart PATTERN...
reload-or-restart PATTERN...
reload-or-try-restart PATTERN...
kill PATTERN...
is-active PATTERN...
is-failed PATTERN...
status [PATTERN...|PID...]]
show [PATTERN...|JOB...]
cat PATTERN...
reset-failed [PATTERN...]
list-dependencies [NAME]
對服務的各種操作:service units
啟動,停止,重啟,查看狀態:start|stop|restart|status
centos5,6:
service NAME start|stop|restart|status
centos7:
systemctl start|stop|restart|status NAME[.service]
後面的.service可以省略# systemctl status crond ● crond.service - Command Scheduler Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2020-02-26 09:28:20 CST; 5h 49min ago
Loaded:已經裝載了。centos5,6則是用chkconfig 命令裝載。
enabled:開機自動啟動
disabled:開機不會自動啟動
InActive/Active:沒有啟動或啟動了。
active(running):一次或多次持續處理的運行
active(exited):成功完成了一次性的配置
active(waiting):運行中,在等待一個事件
static:開機不啟動,但可被另一個啟動的服務激活。
例子:telnet-server。
安裝它後,發現它有2個unit file。其中的[email protected]就是static的,
嘗試啟動[email protected],發現不能啟動,就說明瞭static的不能直接啟動。
那它怎麼啟動呢,啟動telnet.socket就行,telnet.socket啟動後,就變成active (listening)狀態了。
使用
lsof -i :埠號
,可以看到telnet服務是被systemd管理(監管了)。lsof:list open files
# rpm -ql telnet-server /usr/lib/systemd/system/telnet.socket /usr/lib/systemd/system/[email protected] # systemctl list-unit-files -a | grep telnet [email protected] static telnet.socket disabled # systemctl start [email protected] Failed to start [email protected]: Unit name [email protected] is missing the instance name. See system logs and 'systemctl status [email protected]' for details # systemctl is-active telnet.socket unknown # systemctl start telnet.socket # systemctl status telnet.socket ● telnet.socket - Telnet Server Activation Socket Loaded: loaded (/usr/lib/systemd/system/telnet.socket; disabled; vendor preset: disabled) Active: active (listening) since Fri 2020-02-28 10:21:26 CST; 8min ago Docs: man:telnetd(8) Listen: [::]:23 (Stream) Accepted: 0; Connected: 0 # lsof -i :23 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME systemd 1 root 24u IPv6 64689 0t0 TCP *:telnet (LISTEN)
嘗試重啟:try-restart PATTERN...:如果服務不是運行狀態,則說明也不做。
centos7:
# systemctl try-restart httpd
centos5,6:一般的服務腳本里都不支持,此功能,但也有支持的
# service NAME condrestart
重載配置文件或嘗試重啟:reload-or-try-restart PATTERN...
# systemctl reload-or-try-restart httpd
重載配置文件或重啟:reload-or-restart PATTERN...
# systemctl reload-or-restart httpd
查看服務是否是激活:
# systemctl is-active httpd active # systemctl stop httpd # systemctl is-active httpd unknown
列出所有active的service:
# systemctl list-units -t service UNIT LOAD ACTIVE SUB DESCRIPTION abrt-ccpp.service loaded active exited Install ABRT coredump hook abrt-oops.service loaded active running ABRT kernel log watcher
列出所有識別的service:
centos5,6:
chkconfig --list
# systemctl list-units -t service -a
常用的選項:-t和-a
-t:指定unit file的類型
-a:查看全部
禁止手動啟動和開機自動啟動某service:
centos5,6:
chkconfig mySer.sh on
取消禁止手動啟動和開機自動啟動某service
目的是防止誤操作,啟動了不應該啟動的service
原理就是創建一個符號鏈接,所以也可以手動創建符號鏈接實現相同的功能。
# systemctl mask httpd.service Created symlink from /etc/systemd/system/httpd.service to /dev/null. # ll /etc/systemd/system/httpd.service lrwxrwxrwx. 1 root root 9 Feb 27 11:40 /etc/systemd/system/httpd.service -> /dev/null # systemctl start httpd.service Failed to start httpd.service: Unit is masked. # systemctl status httpd.service ● httpd.service Loaded: masked (/dev/null; bad) Active: inactive (dead) # systemctl unmask httpd.service Removed symlink /etc/systemd/system/httpd.service. # ll /etc/systemd/system/httpd.service ls: cannot access /etc/systemd/system/httpd.service: No such file or directory
設置開機自動啟動:
查看某個服務是否是開機自動啟動:
systemctl is-enabled httpd.service
centos5,6:
chkconfig --list NAME
原理就是創建一個符號鏈接,所以也可以手動創建符號鏈接實現相同的功能。
# ll /etc/systemd/system/multi-user.target.wants/ | grep httpd # systemctl is-enabled httpd.service disabled # systemctl enable httpd.service Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service. # ll /etc/systemd/system/multi-user.target.wants/ | grep httpd lrwxrwxrwx. 1 root root 37 Feb 27 11:54 httpd.service -> /usr/lib/systemd/system/httpd.service # systemctl is-enabled httpd.service enabled
目錄/etc/systemd/system/multi-user.target.wants/下的服務就是開機自動啟動的。
查看某個服務依賴了哪些服務:
# systemctl list-dependencies httpd httpd.service ● ├─-.mount ● ├─system.slice ● └─basic.target ● ├─microcode.service ● ├─rhel-dmesg.service
殺死服務,後面是進程的名字,而不是pid,類似,
killall
命令。# systemctl kill httpd
對運行級別的各種操作:target units
unit配置文件:
# ls /usr/lib/systemd/system/*.target
lrwxrwxrwx. 1 root root 15 Nov 29 16:46 /usr/lib/systemd/system/runlevel0.target -> poweroff.target
lrwxrwxrwx. 1 root root 13 Nov 29 16:46 /usr/lib/systemd/system/runlevel1.target -> rescue.target
lrwxrwxrwx. 1 root root 17 Nov 29 16:46 /usr/lib/systemd/system/runlevel2.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 Nov 29 16:46 /usr/lib/systemd/system/runlevel3.target -> multi-user.target
lrwxrwxrwx. 1 root root 17 Nov 29 16:46 /usr/lib/systemd/system/runlevel4.target -> multi-user.target
lrwxrwxrwx. 1 root root 16 Nov 29 16:46 /usr/lib/systemd/system/runlevel5.target -> graphical.target
lrwxrwxrwx. 1 root root 13 Nov 29 16:46 /usr/lib/systemd/system/runlevel6.target -> reboot.target
# systemctl list-unit-files -t target -a
UNIT FILE STATE
anaconda.target static
basic.target static
bluetooth.target static
cryptsetup-pre.target static
cryptsetup.target static
ctrl-alt-del.target disabled
default.target enabled
...
centos5,6里的運行級別是符號鏈接,指向了別的unit
centos5,6里的運行級別 | centos7里的unit file |
---|---|
0 | runlevel0.target ->poweroff.target |
1 | runlevel1.target ->rescue.target |
2 | runlevel2.target ->multi-user.target |
3 | runlevel3.target ->multi-user.target |
4 | runlevel4.target ->multi-user.target |
5 | runlevel5.target ->graphical.target |
6 | runlevel6.target ->reboot.target |
centos5,6里的運行級別是各管各的,centos7里的target可以使用別的target
# systemctl list-dependencies graphical.target
graphical.target
● ├─accounts-daemon.service
● ├─gdm.service
● ├─initial-setup-reconfiguration.service
● ├─network.service
● ├─rtkit-daemon.service
● ├─systemd-readahead-collect.service
● ├─systemd-readahead-replay.service
● ├─systemd-update-utmp-runlevel.service
● ├─udisks2.service
● └─multi-user.target
發現graphical.target是依賴multi-user.target的,也就是graphical.target復用了multi-user.target。
centos5,6要想復用就很麻煩,要手動把腳本拷貝到別的運行級別的目錄里。
切換運行級別:
centos5,6:
init N
centos7:
systemctl isolate NAME.target
who -r
和runlevel
和init N
命令依然在centos7里可以使用。# who -r run-level 5 2020-02-28 09:07 # runlevel N 5 # systemctl isolate multi-user.target # who -r run-level 3 2020-02-28 11:18 last=5 # runlevel 5 3 # systemctl isolate graphical.target # runlevel 3 5 # who -r run-level 5 2020-02-28 11:18 last=3
可以切換的前提條件:NAME.target文件里的AllowIsolate的值必須是yes才可以。
[Unit] Description=Multi-User System Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes
修改unit file後,必須使用
systemctl daemon-reload
命令後,才能生效。修改成AllowIsolate=no # emacs /usr/lib/systemd/system/multi-user.target # tail -1 /usr/lib/systemd/system/multi-user.target AllowIsolate=no 由於沒有運行systemctl daemon-reload命令,所以運行systemctl isolate multi-user.target沒有效果,但是會提示你要運行systemctl daemon-reload命令 # systemctl isolate multi-user.target Warning: multi-user.target changed on disk. Run 'systemctl daemon-reload' to reload units. 讓修改生效 # systemctl daemon-reload 修改已經生效了,所以切換就不成功了。原因是AllowIsolate=no # systemctl isolate multi-user.target Failed to start multi-user.target: Operation refused, unit may not be isolated. See system logs and 'systemctl status multi-user.target' for details.
查看開機時使用的什麼target
# systemctl get-default graphical.target
centos5,6是查看/etc/inittab,centos5里有很多行,centos6只有一行
id:3:initdefault:
設置開機時使用什麼target
原理:創建符號鏈接指向要使用的target
/etc/systemd/system/default.target符號鏈接,指向的是哪個,就使用哪個。所以每次都是先刪除它,再建立一個新的。
# 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. # systemctl set-default graphical.target Removed symlink /etc/systemd/system/default.target. Created symlink from /etc/systemd/system/default.target to /usr/lib/systemd/system/graphical.target.
切換到救援模式:
systemctl rescue
centos7在啟動時,就可以進入救援模式。載入設備驅動。
centos5,6必須藉助光碟才能進入救援模式。
切換到更底層的救援模式:
systemctl emergency
設備驅動都不載入 。如果因為設備驅動壞了導致不能開機,則不許使用此模式修複。
其他常用命令:
原理centos6里的init,poweroff,halt,reboot都成為了systemctl的符號鏈接
# ll /usr/sbin/reboot lrwxrwxrwx. 1 root root 16 Nov 29 16:46 /usr/sbin/reboot -> ../bin/systemctl # ll /usr/sbin/poweroff lrwxrwxrwx. 1 root root 16 Nov 29 16:46 /usr/sbin/poweroff -> ../bin/systemctl
- 關機:
systemctl halt
,systemctl poweroff
- 重啟:
systemctl reboot
- 掛起:
systemctl suspend
- 快照:
systemctl hibernate
- 快照並掛起:
systemctl hybrid-sleep
- 關機:
通過內核參數,臨時修改內核啟動選項
開機時,在選擇的內核上按e鍵,進入grub2的配置,然後在linux16行的最後,添加內核啟動選擇:
- systemd.unit=rescue.target(直接進入救援模式)
- systemd.unit=emergency.target(直接進入救援模式)
- systemd.unit=multi-user.target(直接進入多用戶的文本模式)
編寫unit file
/usr/lib/systemd/system/httpd.service內容如下:
# cat /usr/lib/systemd/system/httpd.service
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)
[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/httpd
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
ExecStop=/bin/kill -WINCH ${MAINPID}
# We want systemd to give httpd some time to finish gracefully, but still want
# it to kill httpd after TimeoutStopSec if something went wrong during the
# graceful stop. Normally, Systemd sends SIGTERM signal right after the
# ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
# httpd time to finish.
KillSignal=SIGCONT
PrivateTmp=true
[Install]
WantedBy=multi-user.target
unit file 通常由3部分組成
- [Unit]:通用選項。
- Description:提供描述信息(在systemctl status里顯示的信息)
- After:在此服務啟動後,本服務啟動
- [Name]:與特定類型相關的專用選項,如果是.service則此處是Service
- [Install]:定義由
systemctl enable
和systemctl disable
命令,在服務啟用或禁用時用到的一些選項。
- [Unit]:通用選項。
以#開頭的行是註釋
相關布爾值
1,yes,on,true都是開啟
2,0,off,no,false都是關閉
時間預設單位是秒,毫秒:ms,分鐘:m等必須顯示加上單位
詳細信息參考阮一峰的日誌:http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html