在 CentOS 7 中使用 systemd 取代了 init 的啓動模式,這樣的更新換代有什麼好處呢?首先須要對 init 和 systemd 有個概念的認識。php
在 CentOS 7 以前的版本中,init 做爲第一個啓動進程,是全部進程的父進程。使用 init 有兩個顯著的缺點:node
(1)啓動時間長。init 進程是串行啓動的,只有前一個進程完成後,纔會啓動下一個進程;nginx
(2)啓動腳本複雜。init 進程只是執行腳本。腳本須要本身處理各類狀況,這樣編寫腳本時就須要考慮到方方面面,腳本會變得冗餘複雜。shell
在 CentOS 7 以後的版本中,使用 systemd 取代了 init 做爲系統的第一個進程啓動,因此 systemd成爲 其餘的進程的父進程,它的目的也是爲了解決 init 所存在的缺點。apache
systemd 相比較 init 優點以下:json
(1)平行處理全部服務,加速開機流程centos
說一個很明顯的例子:在centos 6 和 centos 7 同時開機的狀況下,centos 7 必定是首先啓動完成的,就由於 systemd 採用的是併發執行,而 init 則是串行執行。bash
(2)依 daemon 功能分類session
在 init 中 沒有分類一說,而在 systemd 中一共分爲了 12 個大類(後文介紹)。架構
(3)服務依賴性的自檢
在 systemd 中,若是啓動 B 服務是依賴於 A 服務的,那麼直接啓動 B 服務,A 服務會由於 systemd 自檢而啓動完成。這在 init 中是不會出現的,須要手動一個一個啓動依賴服務。
(4)將多個 daemons 集合成爲一個羣組
這個貌似不是 systemd 特性,在 init 中 init 3 和 init 5 能夠經過 chkconfig --list 來查看定製, 在 systemd 中,對應的是 target,執行某個 target 就是執行一堆 daemon 的集合。
(Systemd 架構圖)
雖然 systemd 看起來很好很強大,可是有沒法取代 init 的地方:
(1)所有的 systemd 都使用 systemctl 管理的,而 systemctl 有固定的語法,沒法作到像 shell 腳本那樣靈活;
(2)systemd 沒法在執行過程當中經過交互來通訊,而 init 只要願意,徹底能夠寫成交互腳本。
systemd 並非一個命令,而是一組命令,涉及到系統管理的不少方面。
4.1 systemctl
systemctl 是 Systemd 的主命令, 這裏主要說明針對系統管理的操做(不經常使用):
# 重啓系統 systemctl reboot # 關閉系統,切斷電源 systemctl poweroff # cpu 中止工做 systemctl halt # 暫停系統 systemctl susend # 讓系統進入冬眠模式 systemctl hibernate # 讓系統進入交互式休眠狀態 systemctl hybrid-sleep # 啓動進入救援狀態(單用戶狀態) systemctl rescue 注:以上命令當心嘗試,做爲了解內容。
4.2 systemd-analyze
systemd-analyze 命令用於查看啓動耗時。
# 查看啓動耗時 systemd-analyze # 查看每一個服務的啓動耗時,從用時長到短排序 systemd-analyze blame # 顯示瀑布的啓動流程 systemd-analyze critical-chain # 顯示指定服務的啓動流 systemd-analyze critical-chain sshd.service
4.3 hostnamectl
hostnamectl 命令用於查看當前主機的信息
# 顯示當前主機信息 hostnamectl # 設置主機名 hostnamectl set-hostname node1
4.4 localectl
localectl 命令用於查看本地化設置
# 查看本地化設置 localectl # 設置本地化參數 localectl set-locale LANG=en_GB.utf8 localectl set-keymap en_GB
4.5 timedatectl
timedatectl 命令用於查看當前時區設置
# 查看當前時區設置 timedatectl # 顯示全部時區 timedatectl list-timezones # 設置當前時區 timedatectl set-timezone Aisa/Shanghai timedatectl set-time YYYY-MM-DD timedatectl set-time HH:MM:SS
4.6 loginctl
loginctl 命令用於查看當前登陸的用戶。
# 列出當前session loginctl list-sessions # 列出當前登陸用戶 loginctl list-users # 列出顯示指定用戶的信息 loginctl show-user root
5.1 含義
Systemd 能夠管理全部系統資源。不一樣的資源統稱爲 Unit(單位)。
Unit 一共分爲 12 種, 使用 systemctl -t help
service 系統服務 socket 進程間通訊的 socket target 多個 Unit 構成的一個組 snapshot systemd 快照,能夠切回某個快照 device 硬件設備 mount 文件系統的掛載點 automount 自動掛載點 swap swap 文件 timer 定時器 path 文件或路徑 slice 進程組 scope 不是由 systemd 啓動的外部進程
systemctl list-units 命令能夠查看當前系統全部的 Unit(服務).
# 列出正在運行的 Unit systemctl list-units # 列出全部的Unit,包括沒有找到配置文件的或啓動失敗的 systemctl list-units --all # 列出全部沒有運行的 Unit systemctl list-units --all --state=inactive # 列出全部加載失敗的 Unit systemctl list-units --failed # 列出全部正在運行的、類型爲 service 的 Unit systemctl list-units --type=service
5.2 Unit 的狀態
systemctl status 命令用於查看系統狀態和單個 Unit 的狀態。
# 顯示系統狀態 systemctl status # 顯示單個 Unit 的狀態 systemctl status httpd.service # 顯示遠程主機的某個 Unit 的狀態 systemctl -H root@node1 status httpd.service
除了 status 命令,systemctl 還提供了三個查詢狀態的簡單方法,主要是腳本內部的判斷語句使用。
# 顯示某個 Unit 是否正在運行 systemctl is-active application.service # 顯示某個 Unit 是否處於啓動失敗狀態 systemctl is-failed application.service # 顯示某個 Unit 服務是否創建了啓動連接 systemctl is-enabled application.service
5.3 Unit 管理
對於用戶來講,最經常使用的是下面這些命令,用於啓動和中止 Unit(主要是 service)
# 當即啓動一個服務 systemctl start apache.service # 當即中止一個服務 systemctl stop apache.service # 重啓一個服務 systemctl restart apache.service # 殺死一個服務的全部子進程 systemctl kill apache.service # 從新加載一個服務的配置文件 systemctl reload apache.service # 重載全部修改過的配置文件 systemctl daemon-reload # 顯示某個 Unit 的全部底層參數 systemctl show httpd.service # 顯示某個 Unit 的指定屬性的值 systemctl show -p CPUShares httpd.service # 設置某個 Unit 的指定屬性 systemctl set-property httpd.service CPUShares=500
5.4 依賴關係
Unit 之間存在依賴關係:A 依賴 B,就意味着 Systemd 在啓動 A 的時候,同時會去啓動 B。
systemctl list-dependencies 命令列出一個 Unit 的全部依賴
某些 target 類型,默認不會展開顯示。若是要展開 target,就須要使用 --all 參數。
systemctl list-dependencies --all httpd.service
6.1 概述
每一個 Unit 都有一個配置文件,告訴 Systemd 怎麼啓動這個 Unit。
systemd 默認從目錄 /etc/systemd/system/ 讀取配置文件,可是這個目錄下大部分文件都是連接文件,指向真正的目錄是 /usr/lib/systemd/system/ ,真正的配置文件存放在這個目錄下。
systemctl enable 命令用於設置開機默認啓動項,也是在 /etc/systemd/system/ 與 /usr/lib/systemd/system/ 之間創建連接。
systemctl disabled 命令用於設置開機默認不啓動項,也就是取消 /etc/systemd/system/ 與 /usr/lib/systemd/system/ 之間創建連接。
# 設置開機啓動 systemctl enable httpd # 設置開機不啓動 systemctl disabled httpd
說明:一個Unit 配置文件只能描述一種單元。
系統提供兩種級別的單元:
當 systemd 以系統實例運行,那麼優先級以下:
6.2 配置文件的狀態
systemctl list-unit-files 命令用於查看列出全部服務的配置文件。
# 列出全部配置文件 systemctl list-unit-files # 列出指定類型的配置文件 systemctl list-unit-files --type=service
這個命令輸出一個列表
這個列表顯示每一個配置文件的狀態,一共有 4 種:
注意:從配置文件的狀態沒法看出,該 Unit 是否正在運行。這必須執行前面提到的 systemctl status 命令。
systemctl status httpd.service
一旦修改了配置文件,就要讓 Systemd 重新載入配置文件,而後從新啓動,不然不會生效。
# 從新加載 systemd systemctl daemon-reload # 重啓服務 systemctl restart httpd.service
6.3 配置文件的格式
配置文件就是普通的文本文件,能夠用文本編輯器打開。
systemctl cat 命令能夠查看配置文件的內容。
[root@localhost ~]# systemctl cat sshd.service # /usr/lib/systemd/system/sshd.service [Unit] Description=OpenSSH server daemon Documentation=man:sshd(8) man:sshd_config(5) After=network.target sshd-keygen.service Wants=sshd-keygen.service [Service] EnvironmentFile=/etc/sysconfig/sshd ExecStart=/usr/sbin/sshd -D $OPTIONS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target
從上面能夠看到,配置文件分紅幾個區塊,每一個區塊的第一行,是用中括號表示的區別名,如:[Unit] 注意:配置文件的區塊名和字段名,都是大小寫敏感的。
每一個區塊內都是一些等號的鏈接的鍵值對。
6.4 配置文件的區塊
[Unit] 區塊一般是配置文件的第一個區塊。用來定義 Unit 的元數據,以及配置與其餘 Unit 的關係。主要字段以下:
Description:簡短描述 Documentation:文檔地址 Requires:當前 Unit 依賴的其餘 Unit,若是它們沒有運行,當前 Unit 會啓動失敗 Wants:與當前 Unit 配合的其餘 Unit,若是它們沒有運行,當前 Unit 不會啓動失敗 BindsTo:與Requires相似,它指定的 Unit 若是退出,會致使當前 Unit 中止運行 Before:若是該字段指定的 Unit 也要啓動,那麼必須在當前 Unit 以後啓動 After:若是該字段指定的 Unit 也要啓動,那麼必須在當前 Unit 以前啓動 Conflicts:這裏指定的 Unit 不能與當前 Unit 同時運行 Condition...:當前 Unit 運行必須知足的條件,不然不會運行 Assert...:當前 Unit 運行必須知足的條件,不然會報啓動失敗
[Install] 一般是配置文件的最後一個區塊,用來定義如何啓動,以及是否開機啓動。這個區塊包含Unit 啓動信息,只有單元狀態爲 enable 或者 disabled 纔會用到這個段,通俗來講:設置開機啓動模式(enable 、 disabled)纔會用到這個區塊。
主要字段以下:
WantedBy:它的值是一個或多個 Target,當前 Unit 激活時(enable)符號連接會放入/etc/systemd/system目錄下面以 Target 名 + .wants後綴構成的子目錄中。如:/etc/systemd/system/multi-user.target.wants/sshd.service RequiredBy:它的值是一個或多個 Target,當前 Unit 激活時,符號連接會放入/etc/systemd/system目錄下面以 Target 名 + .required後綴構成的子目錄中 Alias:當前 Unit 可用於啓動的別名 Also:當前 Unit 激活(enable)時,會被同時激活的其餘 Unit
[Service] 區塊用來 Service 的配置,只有 Service 類型的 Unit 纔有這個區塊。它的主要字段以下:
Type:定義啓動時的進程行爲。它有如下幾種值。
Type=simple:默認值,執行ExecStart指定的命令,啓動主進程
Type=forking:以 fork 方式從父進程建立子進程,建立後父進程會當即退出
Type=oneshot:一次性進程,Systemd 會等當前服務退出,再繼續往下執行
Type=dbus:當前服務經過D-Bus啓動
Type=notify:當前服務啓動完畢,會通知Systemd,再繼續往下執行 # 常見Unit 採用這種方式,如 httpd
Type=idle:如有其餘任務執行完畢,當前服務纔會運行
-----------------------------------------------------------------------
ExecStart:啓動當前服務的命令
ExecStartPre:啓動當前服務以前執行的命令
ExecStartPost:啓動當前服務以後執行的命令
ExecReload:重啓當前服務時執行的命令
ExecStop:中止當前服務時執行的命令
ExecStopPost:中止當其服務以後執行的命令
RestartSec:自動重啓當前服務間隔的秒數
Restart:定義何種狀況 Systemd 會自動重啓當前服務,可能的值包括always(老是重啓)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
TimeoutSec:定義 Systemd 中止當前服務以前等待的秒數
Environment:指定環境變量
啓動計算機的時候,須要啓動大量的 Unit。若是每次啓動,都要申明本次啓動的全部 Unit,顯然不太方便。systemd 的解決方案是: Target
簡單說,Target 就是一個 Unit 組,啓動某個 Target ,systemd 就會啓動包含在這裏 Target 裏的 Unit。
傳統的 init 啓動模式裏,有 Runlevel 的概念,跟 Target 的做用很相似。不一樣的是,Runlevel 是互斥的,不可能多個Runlevel 同時啓動,可是多個 Target 能夠同時啓動。
# 查看當前系統的全部 Target systemctl list-unit-files --type=target # 查看一個 Target 包含的全部 Unit systemctl list-dependencies multi-user.target # 查看啓動時的默認 Target systemctl get-default # 設置啓動時的默認 Target systemctl set-default multi-user.target 切換 Target 時,默認不關閉前一個 Target 啓動的進程,systemctl isolate 命令改變這種行爲。 # 關閉前一個 Target 裏面全部不屬於後一個 Target 的進程 systemctl isolate multi-user.target
經常使用的 Target 有以下:
Target 和 init 進程的主要區別:
(1)默認的 RunLevel(在 /etc/inittab 文件設置)如今被默認的 Target 取代,位置是 /etc/systemd/system/default.target,一般符號連接 graphical.target(圖形界面)或者 multi-user.target (多用戶命令行);
(2)啓動腳本位置,之前是 /etc/init.d/ 目錄,符號連接到不一樣的 RunLevel 目錄(好比:/etc/rc3.d/ 、/etc/rc5.d/)如今則存放在 /lib/systemd/system/ 和 /etc/systemd/system/ 目錄;
(3)配置文件的位置,之前 init 進程的配置文件是 /etc/inittab ,各類服務的配置文件存放在 /etc/sysconfig/ 目錄。如今的配置文件主要存放在 /lib/systemd 目錄,在 /etc/systemd 目錄裏面的修改能夠覆蓋原始設置。
8. 日誌管理
Systemd 統一管理全部 Unit 的啓動日誌。帶來的好處就是,能夠只用 journalctl 一個命令,查看全部日誌(內核日誌和應用日誌)。日誌的配置文件是 /etc/systemd/journald.conf
# 查看全部日誌(默認狀況下 ,只保存本次啓動的日誌) journalctl # 查看內核日誌(不顯示應用日誌) journalctl -k # 查看系統本次啓動的日誌 journalctl -b journalctl -b -0 # 查看上一次啓動的日誌(需更改設置) journalctl -b -1 # 查看指定時間的日誌 journalctl --since="2012-10-30 18:17:16" journalctl --since "20 min ago" journalctl --since yesterday journalctl --since "2015-01-10" --until "2015-01-11 03:00" journalctl --since 09:00 --until "1 hour ago" # 顯示尾部的最新10行日誌 journalctl -n # 顯示尾部指定行數的日誌 journalctl -n 20 # 實時滾動顯示最新日誌 journalctl -f # 查看指定服務的日誌 journalctl /usr/lib/systemd/systemd # 查看指定進程的日誌 journalctl _PID=1 # 查看某個路徑的腳本的日誌 journalctl /usr/bin/bash # 查看指定用戶的日誌 journalctl _UID=33 --since today # 查看某個 Unit 的日誌 journalctl -u nginx.service journalctl -u nginx.service --since today # 實時滾動顯示某個 Unit 的最新日誌 journalctl -u nginx.service -f # 合併顯示多個 Unit 的日誌 $ journalctl -u nginx.service -u php-fpm.service --since today # 查看指定優先級(及其以上級別)的日誌,共有8級 # 0: emerg # 1: alert # 2: crit # 3: err # 4: warning # 5: notice # 6: info # 7: debug journalctl -p err -b # 日誌默認分頁輸出,--no-pager 改成正常的標準輸出 journalctl --no-pager # 以 JSON 格式(單行)輸出 journalctl -b -u nginx.service -o json # 以 JSON 格式(多行)輸出,可讀性更好 journalctl -b -u nginx.serviceqq -o json-pretty # 顯示日誌佔據的硬盤空間 journalctl --disk-usage # 指定日誌文件佔據的最大空間 journalctl --vacuum-size=1G # 指定日誌文件保存多久 journalctl --vacuum-time=1years