CentOS 7使用Systemd替換了SysV。Systemd目的是要取代Unix時代以來一直在使用的init系統,兼容SysV和LSB的啓動腳本,並且夠在進程啓動過程當中更有效地引導加載服務。php
Systemd的特性前端
支持並行化任務
同時採用socket式與D-Bus總線式激活服務
按需啓動守護進程(daemon)
利用Linux的cgroups監視進程
支持快照和系統恢復
維護掛載點和自動掛載點
各服務間基於依賴關係進行精密控制nginx
在Linux中,init就是initialization(初始化)的縮寫。init是一個daemon(後臺)進程, 它是Linux系統開機啓動(內核加載完畢)後運行的第一個進程,進程號(pid)爲1。直到系統關機它才終止運行,也就是說它也是Linux系統關機前運行的最後一個進程。sql
Linux系統中全部其餘進程都是直接或間接由init進程啓動的, 所以init進程是其餘全部進程的父進程或祖先進程。 所以它能夠作許多其餘進程不能作的事情,接管其餘進程不負責的功能。json
正是因爲其特殊性, 萬一init由於某種緣由不能啓動,那麼Linux系統就再也沒法啓動其餘進程, 系統就會處於Kernel Panic
狀態。bash
Systemd是System Management Daemon的簡寫(在UNIX系統中,後臺進程都按照慣例以d結尾,所以當你看到一個進程的名字以d結尾,那它極有多是一個後臺進程), 它是Linux系統中啓動的第一個進程,也就上面所說的init daemon進程。服務器
Systemd的優勢是功能強大,使用方便,缺點是體系龐大,很是複雜。事實上,如今還有不少人反對使用Systemd,理由就是它過於複雜,與操做系統的其餘部分強耦合,違反keep simple, keep stupid
的Unix哲學。網絡
Systemd架構圖session
Systemd基本工具
架構
Systemd並非一個命令,而是一組命令,涉及到系統管理的方方面面。
systemd-analyze命令用於查看啓動耗時。
開機啓動過程
Systemd最基本的任務是管理開機啓動過程,並提供開機啓動的一些信息。
想獲得開機啓動時間,運行下面命令
$ systemd-analyze
想獲得開機時每個任務啓動的時間,運行下面命令
$ systemd-analyze blame
想獲得更多的啓動信息,systemd-analyze 這個命令也能夠經過如下命令生成一個描述各個啓動任務信息的svg格式圖片
$ systemd-analyze plot > plot.svg
顯示瀑布狀的啓動過程流
$ systemd-analyze critical-chain
顯示指定服務的啓動流
$ systemd-analyze critical-chain atd.service
檢視和控制Systemd的主要命令是systemctl。該命令可用於查看系統狀態和管理系統及服務。詳見man 1 systemctl
。
在systemctl參數中添加-H <用戶名>@<主機名>
能夠實現對其餘機器的遠程控制。該過程使用ssh連接。systemadm是Systemd的官方圖形前端。
# 啓動進入救援狀態(單用戶狀態) $ systemctl rescue # CPU中止工做 $ systemctl halt # 重啓系統 $ systemctl reboot # 關閉系統,切斷電源 $ systemctl poweroff # 暫停系統 $ systemctl suspend # 讓系統進入冬眠狀態 $ systemctl hibernate # 讓系統進入交互式休眠狀態 $ systemctl hybrid-sleep # 讓系統進入進入緊急模式 $ systemctl emergency # 經過ssh遠程控制主機 $ systemctl --host user_name@host_name command $ systemctl -H user_name@host_name command
Systemd統一管理全部Unit的啓動日誌。帶來的好處就是,能夠只用journalctl一個命令,查看全部日誌(內核日誌和應用日誌)。日誌的配置文件是/etc/systemd/journald.conf
。
journalctl功能強大,用法很是多。
# 查看全部日誌(默認狀況下 ,只保存本次啓動的日誌) $ journalctl # 查看內核日誌(不顯示應用日誌) $ journalctl -k # 查看系統本次啓動的日誌 $ journalctl -b $ journalctl -b -0 # 查看上一次啓動的日誌(需更改設置) $ journalctl -b -1 $ journalctl -b caf0524a1d394ce0bdbcff75b94444fe # 查看指定時間的日誌 $ 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" $ journalctl --since=today $ journalctl --since "2015-06-01 01:00:00" $ journalctl --since "2015-06-01" --until "2015-06-13 15: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 $ journalctl _UID=33 --since today # 查看指定用組的日誌 $ journalctl _GID=33 # 查看指定字段的數據 $ journalctl -F _GID # 查看某個Unit的日誌 $ journalctl -u nginx.service $ journalctl -u nginx.service --since today $ journalctl -u nginx.service -u postgresql.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 格式(多行)輸出,可讀性更好 format: * cat * export * json * json-pretty * json-sse * short * short-iso * short-monotonic * short-precise * verbose $ journalctl -b -u nginx.service -o json-pretty # 顯示日誌佔據的硬盤空間 $ journalctl --disk-usage # 指定日誌文件佔據的最大空間 $ journalctl --vacuum-size=1G # 指定日誌文件保存多久 $ journalctl --vacuum-time=1years # 查看某個應用的日誌 $ journalctl /sbin/crond $ journalctl `which crond` # 以UTC時間格式顯示日誌 $ journalctl --utc # 簡潔顯示有關啓動的日誌 $ journalctl --list-boots # 顯示有關內核啓動的日誌 $ journalctl -k
hostnamectl命令用於查看當前主機的信息。
# 顯示當前主機的信息 $ hostnamectl # 設置主機名。 $ hostnamectl set-hostname <hostname>
localectl命令用於查看本地化設置。
# 查看本地化設置 $ localectl $ localectl status $ localectl list-locales $ localectl list-keymaps # 設置本地化參數。 $ localectl set-locale.utf8 $ localectl set-keymap en_GB $ localectl set-x11-keymap en_GB
timedatectl命令用於查看當前時區設置。
# 查看當前時區設置 $ timedatectl # 顯示全部可用的時區 $ timedatectl list-timezones # 顯示系統的當前時間和日期 $ timedatectl status # 設置當前時區 $ timedatectl set-timezone America/New_York $ timedatectl set-timezone UTC $ timedatectl set-time YYYY-MM-DD $ timedatectl set-time HH:MM:SS $ timedatectl set-time 'YYYY-MM-DD HH:MM:SS' $ timedatectl set-local-rtc boolean # yes/no $ timedatectl set-ntp boolean # 設置硬件時鐘以協調世界時UTC $ timedatectl | grep local #首先肯定你的硬件時鐘是否設置爲本地時區 $ timedatectl set-local-rtc 1 #將你的硬件時鐘設置爲本地時區 $ timedatectl set-local-rtc 0 #將你的硬件時鐘設置爲協調世界時 # 將Linux系統時鐘同步到遠程NTP服務器 $ timedatectl set-ntp true #自動時間同步到遠程NTP服務器 $ timedatectl set-ntp false #禁用NTP時間同步 注意:你必須在系統上安裝NTP以實現與NTP服務器的自動時間同步。
loginctl命令用於查看當前登陸的用戶。
# 列出當前session $ loginctl list-sessions # 列出當前登陸用戶 $ loginctl list-users # 列出顯示指定用戶的信息 $ loginctl show-user tom
與系統加載相關命令
$ bootctl status $ bootctl update $ bootctl install $ bootctl remove
$ busctl $ machinectl $ networkctl $ systemd-cgtop $ systemd-cgls
系統啓動過程當中,Systemd用Unit來組織那些各類不一樣的任務, 例如生成網絡端口、配置硬件設備、加載存儲設備、開啓後臺服務進程、等等
Systemd要求每個任務對應一個Unit, 而每個Unit都須要一個包含必要信息的配置文件,而這些配置文件的語法很簡單,這也是Systemd的要實現的目的之一。
Systemd能夠管理全部系統資源。不一樣的資源統稱爲Unit(單位)。
Unit一共分紅12種
Service unit:系統服務
Target unit:多個Unit構成的一個組
Device Unit:硬件設備
Mount Unit:文件系統的掛載點
Automount Unit:自動掛載點
Path Unit:文件或路徑
Scope Unit:不是由Systemd啓動的外部進程
Slice Unit:進程組
Snapshot Unit:Systemd快照,能夠切回某個快照
Socket Unit:進程間通訊的socket
Swap Unit:swap文件
Timer Unit:定時器
Systemd經過配置文件的後綴名來判斷unit的類型,好比一個service類型的unit的配置文件名一般相似於name.service, 一個mount類型的unit的配置文件名一般相似於name.mount。
# 設置開機自啓動某服務 $ systemctl enable name.service# 中止開機自啓動某服務 $ systemctl disable name.service# 屏蔽(讓它不能啓動)或顯示一個或多個服務 $ systemctl mask name.service# 取消屏蔽(讓它不能啓動)或顯示一個或多個服務 $ systemctl unmask name.service# 查看Unit配置文件的內容 $ systemctl cat name.service# 編輯Unit配置文件的內容 $ systemctl edit name.service# 顯示Unit配置文件的內容 $ systemctl show name.service $ systemctl show name.service -p property # 查看當前系統的全部Unit $ systemctl list-units # 列出全部Unit,包括沒有找到配置文件的或者啓動失敗的 $ systemctl list-units --all # 列出全部沒有運行的Unit $ systemctl list-units --all --state=inactive $ systemctl list-units --type service --all --state=inactive # 列出全部加載失敗的Unit $ systemctl list-units --failed # 列出全部正在運行的、類型爲service的Unit $ systemctl list-units --type=service # 列出全部服務 $ systemctl list-unit-files
systemctl status命令用於查看系統狀態和單個Unit的狀態。
# 顯示系統狀態 $ systemctl status # 顯示單個Unit的狀態 $ sysystemctl status bluetooth.service # 顯示遠程主機的某個Unit的狀態 $ systemctl -H root@rhel7.example.com status httpd.service 除了status命令,systemctl還提供了三個查詢狀態的簡單方法,主要供腳本內部的判斷語句使用。 # 顯示某個Unit是否正在運行 $ systemctl is-active application.service # 顯示某個Unit是否處於啓動失敗狀態 $ systemctl is-failed application.service # 顯示某個Unit服務是否創建了啓動連接 $ systemctl is-enabled application.service
對於用戶來講,最經常使用的是下面這些命令,用於啓動和中止Unit(主要是 service)。
# 當即啓動一個服務 $ systemctl start name.service # 當即中止一個服務 $ systemctl stop name.service # 重啓一個服務 $ systemctl restart name.service #從新啓動一個或多個已經激活的服務 $ systemctl try-restart name.service # 殺死一個服務的全部子進程 $ systemctl kill name.service # 從新加載一個服務的配置文件 $ systemctl reload name.service # 重載全部修改過的配置文件 $ systemctl daemon-reload # 顯示某個Unit的全部底層參數 $ systemctl show httpd.service # 顯示某個Unit的指定屬性的值 $ systemctl show -p CPUShares httpd.service # 設置某個Unit的指定屬性 $ systemctl set-property httpd.service CPUShares=500
Unit之間存在依賴關係:A依賴於B,就意味着Systemd在啓動A的時候,同時會去啓動B。
列出一個Unit的全部依賴。
$ systemctl list-dependencies nginx.service
上面命令的輸出結果之中,有些依賴是Target類型,默認不會展開顯示。若是要展開Target,就須要使用--all
參數。
$ systemctl list-dependencies --all nginx.service
Systemd會自動生成一些unit
,而這些unit
並不會存在配置文件,可是它們能夠經過systemctl來訪問。
每個Unit都有一個配置文件,告訴Systemd怎麼啓動這Unit。Systemd默認從目錄/etc/systemd/system/
讀取配置文件。可是裏面存放的大部分文件都是符號連接,指向目錄/usr/lib/systemd/system/
,真正的配置文件存放在那個目錄。
systemctl enable
命令用於在上面兩個目錄之間,創建符號連接關係。
$ systemctl enable clamd@scan.service
等同於
$ ln -s '/usr/lib/systemd/system/clamd@scan.service' '/etc/systemd/system/multi-user.target.wants/clamd@scan.service'
若是配置文件裏面設置了開機啓動,systemctl enable
命令至關於激活開機啓動。
與之對應的,systemctl disable
命令用於在兩個目錄之間,撤銷符號連接關係,至關於撤銷開機啓動。
$ systemctl disable clamd@scan.service
配置文件的後綴名,就是該Unit的種類,好比sshd.socket。若是省略,Systemd 默認後綴名爲.service,因此sshd會被理解成sshd.service。
注: 若是同一個配置文件名都處於這兩個文件夾中, systemd會忽略/usr/lib/systemd/system/
中的同名配置文件。
systemctl list-unit-files
命令用於列出全部配置文件。
# 列出全部配置文件 $ systemctl list-unit-files # 列出指定類型的配置文件 $ systemctl list-unit-files --type=service
這個命令會輸出一個列表。
$ systemctl list-unit-files UNIT FILE STATE chronyd.service enabled clamd@.service static clamd@scan.service disabled
這個列表顯示每一個配置文件的狀態,一共有四種。
enabled:已創建啓動連接
disabled:沒創建啓動連接
static:該配置文件沒有[Install]部分(沒法執行),只能做爲其餘配置文件的依賴
masked:該配置文件被禁止創建啓動連接
注意,從配置文件的狀態沒法看出,該Unit是否正在運行。這必須執行前面提到的systemctl status
命令。
$ systemctl status bluetooth.service
一旦修改配置文件,就要讓SystemD從新加載配置文件,而後從新啓動,不然修改不會生效。
$ systemctl daemon-reload $ systemctl restart httpd.service
配置文件就是普通的文本文件,能夠用文本編輯器打開。
systemctl cat
命令能夠查看配置文件的內容。
$ systemctl cat atd.service [Unit] Description=ATD daemon [Service] Type=forking ExecStart=/usr/bin/atd [Install] WantedBy=multi-user.target
從上面的輸出能夠看到,配置文件分紅幾個區塊。每一個區塊的第一行,是用方括號表示的區別名,好比[Unit]。注意,配置文件的區塊名和字段名,都是大小寫敏感的。
每一個區塊內部是一些等號鏈接的鍵值對。
[Section] Directive1=value Directive2=value . . .
注意:鍵值對的等號兩側不能有空格。
[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]一般是配置文件的最後一個區塊,用來定義如何啓動,以及是否開機啓動。它的主要字段以下
WantedBy:它的值是一個或多個 Target,當前 Unit 激活時(enable)符號連接會放入/etc/systemd/system目錄下面以 Target 名 + .wants後綴構成的子目錄中
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,再繼續往下執行
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組,包含許多相關的Unit 。啓動某個Target的時候,Systemd就會啓動裏面全部的Unit。從這個意義上說,Target這個概念相似於[狀態點],啓動某個Target就比如啓動到某種狀態。
傳統的init啓動模式裏面,有RunLevel的概念,跟Target的做用很相似。不一樣的是RunLevel是互斥的,不可能多個RunLevel同時啓動,可是多個Target能夠同時啓動。
它與init進程的主要差異以下
默認的RunLevel(在/etc/inittab文件設置)如今被默認的 Target 取代,位置是/etc/systemd/system/default.target,一般符號連接到graphical.target(圖形界面)或者multi-user.target(多用戶命令行)。
啓動腳本的位置,之前是/etc/init.d目錄,符號連接到不一樣的 RunLevel 目錄 (好比/etc/rc3.d、/etc/rc5.d等),如今則存放在/lib/systemd/system和/etc/systemd/system目錄。
配置文件的位置,之前init進程的配置文件是/etc/inittab,各類服務的配置文件存放在/etc/sysconfig目錄。如今的配置文件主要存放在/lib/systemd目錄,在/etc/systemd目錄裏面的修改能夠覆蓋原始設置。
Target與傳統RunLevel的對應關係以下
Traditional runlevel New target name Symbolically linked to... Runlevel 0 | runlevel0.target -> poweroff.target Runlevel 1 | runlevel1.target -> rescue.target Runlevel 2 | runlevel2.target -> multi-user.target Runlevel 3 | runlevel3.target -> multi-user.target Runlevel 4 | runlevel4.target -> multi-user.target Runlevel 5 | runlevel5.target -> graphical.target Runlevel 6 | runlevel6.target -> reboot.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