Systemd 是一系列工具的集合,其作用也遠遠不僅是啟動操作系統(tǒng),它還接管了后臺服務、結(jié)束、狀態(tài)查詢,以及日志歸檔、設(shè)備管理、電源管理、定時任務等許多職責,并支持通過特定事件(如插入特定 USB 設(shè)備)和特定端口數(shù)據(jù)觸發(fā)的 On-demand(按需)任務。
Systemd 的后臺服務還有一個特殊的身份——它是系統(tǒng)中 PID 值為 1 的進程。
Systemd 提供了 服務按需啟動 的能力,使得特定的服務只有在真定被請求時才啟動。
在 SysV-init 時代,將每個服務項目編號依次執(zhí)行啟動腳本。Ubuntu 的 Upstart 解決了沒有直接依賴的啟動之間的并行啟動。而 Systemd 通過 Socket 緩存、DBus 緩存和建立臨時掛載點等方法進一步解決了啟動進程之間的依賴,做到了所有系統(tǒng)服務并發(fā)啟動。對于用戶自定義的服務,Systemd 允許配置其啟動依賴項目,從而確保服務按必要的順序運行。
在 Systemd 之間的主流應用管理服務都是使用 進程樹 來跟蹤應用的繼承關(guān)系的,而進程的父子關(guān)系很容易通過 兩次 fork 的方法脫離。
而 Systemd 則提供通過 CGroup 跟蹤進程關(guān)系,引補了這個缺漏。通過 CGroup 不僅能夠?qū)崿F(xiàn)服務之間訪問隔離,限制特定應用程序?qū)ο到y(tǒng)資源的訪問配額,還能更精確地管理服務的生命周期。
Systemd 是一系列工具的集合, 包括了一個專用的系統(tǒng)日志管理服務:Journald。這個服務的設(shè)計初衷是克服現(xiàn)有 Syslog 服務的日志內(nèi)容易偽造和日志格式不統(tǒng)一等缺點,Journald 用 二進制格式 保存所有的日志信息,因而日志內(nèi)容很難被手工偽造。Journald 還提供了一個 journalctl 命令來查看日志信息,這樣就使得不同服務輸出的日志具有相同的排版格式, 便于數(shù)據(jù)的二次處理。
Systemd 可以管理所有系統(tǒng)資源,不同的資源統(tǒng)稱為 Unit(單位)。
在 Systemd 的生態(tài)圈中,Unit 文件統(tǒng)一了過去各種不同系統(tǒng)資源配置格式,例如服務的啟/停、定時任務、設(shè)備自動掛載、網(wǎng)絡配置、虛擬內(nèi)存配置等。而 Systemd 通過不同的文件后綴來區(qū)分這些配置文件。
Unit 文件按照 Systemd 約定,應該被放置指定的三個系統(tǒng)目錄之一中。這三個目錄是有優(yōu)先級的,如下所示,越靠上的優(yōu)先級越高。因此,在三個目錄中有同名文件的時候,只有優(yōu)先級最高的目錄里的那個文件會被使用。
Systemd 默認從目錄 /etc/systemd/system/ 讀取配置文件。但是,里面存放的大部分文件都是符號鏈接,指向目錄 /usr/lib/systemd/system/,真正的配置文件存放在那個目錄。
Unit 是 Systemd 管理系統(tǒng)資源的基本單元,可以認為每個系統(tǒng)資源就是一個 Unit,并使用一個 Unit 文件定義。在 Unit 文件中需要包含相應服務的描述、屬性以及需要運行的命令。
Target 是 Systemd 中用于指定系統(tǒng)資源啟動組的方式,相當于 SysV-init 中的運行級別。
簡單說,Target 就是一個 Unit 組,包含許多相關(guān)的 Unit 。啟動某個 Target 的時候,Systemd 就會啟動里面所有的 Unit。從這個意義上說,Target 這個概念類似于”狀態(tài)點”,啟動某個 Target 就好比啟動到某種狀態(tài)。
[Unit]
Description=Hello World
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill busybox1
ExecStartPre=-/usr/bin/docker rm busybox1
ExecStartPre=/usr/bin/docker pull busybox
ExecStart=/usr/bin/docker run --name busybox1 busybox /bin/ sh -c 'while true; do echo Hello World; sleep 1; done'
ExecStop='/usr/bin/docker stop busybox1'
ExecStopPost='/usr/bin/docker rm busybox1'
[Install]
WantedBy=multi-user.target
如下所示,Systemd 服務的 Unit 文件可以分為三個配置區(qū)段:
這部分配置的目標模塊通常是特定運行目標的 .target 文件,用來使得服務在系統(tǒng)啟動時自動運行。這個區(qū)段可以包含三種啟動約束:
# find /etc/systemd/system/* -type d
/etc/systemd/system/default.target.wants
/etc/systemd/system/getty.target.wants
/etc/systemd/system/graphical.target.wants
/etc/systemd/system/multi-user.target.wants
/etc/systemd/system/network-online.target.wants
/etc/systemd/system/paths.target.wants
/etc/systemd/system/shutdown.target.wants
/etc/systemd/system/sockets.target.wants
/etc/systemd/system/sysinit.target.wants
/etc/systemd/system/timers.target.wants
通過 systemctl list-units --type=target 命令可以獲取當前正在使用的運行目標
# systemctl list-units --type=target
UNIT LOAD ACTIVE SUB DESCRIPTION
basic.target loaded active active Basic System
cryptsetup.target loaded active active Encrypted Volumes
getty.target loaded active active Login Prompts
graphical.target loaded active active Graphical Interface
local-fs-pre.target loaded active active Local File Systems (Pre)
local-fs.target loaded active active Local File Systems
multi-user.target loaded active active Multi-User System
network-online.target loaded active active Network is Online
network.target loaded active active Network
nss-user-lookup.target loaded active active User and Group Name Lookups
paths.target loaded active active Paths
remote-fs-pre.target loaded active active Remote File Systems (Pre)
remote-fs.target loaded active active Remote File Systems
slices.target loaded active active Slices
sockets.target loaded active active Sockets
sound.target loaded active active Sound Card
swap.target loaded active active Swap
sysinit.target loaded active active System Initialization
time-sync.target loaded active active System Time Synchronized
timers.target loaded active active Timers
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.
20 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
用來 Service 的配置,只有 Service 類型的 Unit 才有這個區(qū)塊。它的主要字段分為服務生命周期和服務上下文配置兩個方面。
注意:如果在 ExecStart、ExecStop 等屬性中使用了 Linux 命令,則必須要寫出完整的絕對路徑。對于 ExecStartPre 和 ExecStartPost 輔助命令,若前面有個 “-” 符號,表示忽略這些命令的出錯。因為有些 “輔助” 命令本來就不一定成功,比如嘗試清空一個文件,但文件可能不存在。
在 Unit 文件中,有時會需要使用到一些與運行環(huán)境有關(guān)的信息,例如節(jié)點 ID、運行服務的用戶等。這些信息可以使用占位符來表示,然后在實際運行被動態(tài)地替換實際的值。
在現(xiàn)實中,往往有一些應用需要被復制多份運行。例如,用于同一個負載均衡器分流的多個服務實例,或者為每個 SSH 連接建立一個獨立的 sshd 服務進程。
Unit 模板文件的寫法與普通的服務 Unit 文件基本相同,不過 Unit 模板的文件名是以 @ 符號結(jié)尾的。通過模板啟動服務實例時,需要在其文件名的 @ 字符后面附加一個參數(shù)字符串。
[Unit]
Description=My Advanced Service Template
After=etcd.service docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill apache%i
ExecStartPre=-/usr/bin/docker rm apache%i
ExecStartPre=/usr/bin/docker pull coreos/apache
ExecStart=/usr/bin/docker run --name apache%i -p %i:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStartPost=/usr/bin/etcdctl set /domains/example.com/%H:%i running
ExecStop=/usr/bin/docker stop apache1
ExecStopPost=/usr/bin/docker rm apache1
ExecStopPost=/usr/bin/etcdctl rm /domains/example.com/%H:%i
[Install]
WantedBy=multi-user.target
在服務啟動時需要在 @ 后面放置一個用于區(qū)分服務實例的附加字符參數(shù),通常這個參數(shù)用于監(jiān)控的端口號或控制臺 TTY 編譯號。
# systemctl start apache@8080.service
Systemd 在運行服務時,總是會先嘗試找到一個完整匹配的 Unit 文件,如果沒有找到,才會嘗試選擇匹配模板。例如上面的命令,System 首先會在約定的目錄下尋找名為 apache@8080.service 的文件,如果沒有找到,而文件名中包含 @ 字符,它就會嘗試去掉后綴參數(shù)匹配模板文件。對于 apache@8080.service,systemd 會找到 apache@.service 模板文件,并通過這個模板文件將服務實例化。
# systemctl --help
systemctl [OPTIONS...] {COMMAND} ...
Query or send control commands to the systemd manager.
-h --help Show this help
--version Show package version
--system Connect to system manager
-H --host=[USER@]HOST
Operate on remote host
-M --machine=CONTAINER
Operate on local container
-t --type=TYPE List units of a particular type
--state=STATE List units with particular LOAD or SUB or ACTIVE state
-p --property=NAME Show only properties by this name
-a --all Show all loaded units/properties, including dead/empty
ones. To list all units installed on the system, use
the 'list-unit-files' command instead.
-l --full Don't ellipsize unit names on output
-r --recursive Show unit list of host and local containers
--reverse Show reverse dependencies with 'list-dependencies'
--job-mode=MODE Specify how to deal with already queued jobs, when
queueing a new job
--show-types When showing sockets, explicitly show their type
-i --ignore-inhibitors
When shutting down or sleeping, ignore inhibitors
--kill-who=WHO Who to send signal to
-s --signal=SIGNAL Which signal to send
--now Start or stop unit in addition to enabling or disabling it
-q --quiet Suppress output
--no-block Do not wait until operation finished
--no-wall Don't send wall message before halt/power-off/reboot
--no-reload Don't reload daemon after en-/dis-abling unit files
--no-legend Do not print a legend (column headers and hints)
--no-pager Do not pipe output into a pager
--no-ask-password
Do not ask for system passwords
--global Enable/disable unit files globally
--runtime Enable unit files only temporarily until next reboot
-f --force When enabling unit files, override existing symlinks
When shutting down, execute action immediately
--preset-mode= Apply only enable, only disable, or all presets
--root=PATH Enable unit files in the specified root directory
-n --lines=INTEGER Number of journal entries to show
-o --output=STRING Change journal output mode (short, short-iso,
short-precise, short-monotonic, verbose,
export, json, json-pretty, json-sse, cat)
--plain Print unit dependencies as a list instead of a tree
Unit Commands:
list-units [PATTERN...] List loaded units
list-sockets [PATTERN...] List loaded sockets ordered by address
list-timers [PATTERN...] List loaded timers ordered by next elapse
start NAME... Start (activate) one or more units
stop NAME... Stop (deactivate) one or more units
reload NAME... Reload one or more units
restart NAME... Start or restart one or more units
try-restart NAME... Restart one or more units if active
reload-or-restart NAME... Reload one or more units if possible,
otherwise start or restart
reload-or-try-restart NAME... Reload one or more units if possible,
otherwise restart if active
isolate NAME Start one unit and stop all others
kill NAME... Send signal to processes of a unit
is-active PATTERN... Check whether units are active
is-failed PATTERN... Check whether units are failed
status [PATTERN...|PID...] Show runtime status of one or more units
show [PATTERN...|JOB...] Show properties of one or more
units/jobs or the manager
cat PATTERN... Show files and drop-ins of one or more units
set-property NAME ASSIGNMENT... Sets one or more properties of a unit
help PATTERN...|PID... Show manual for one or more units
reset-failed [PATTERN...] Reset failed state for all, one, or more
units
list-dependencies [NAME] Recursively show units which are required
or wanted by this unit or by which this
unit is required or wanted
Unit File Commands:
list-unit-files [PATTERN...] List installed unit files
enable NAME... Enable one or more unit files
disable NAME... Disable one or more unit files
reenable NAME... Reenable one or more unit files
preset NAME... Enable/disable one or more unit files
based on preset configuration
preset-all Enable/disable all unit files based on
preset configuration
is-enabled NAME... Check whether unit files are enabled
mask NAME... Mask one or more units
unmask NAME... Unmask one or more units
link PATH... Link one or more units files into
the search path
add-wants TARGET NAME... Add 'Wants' dependency for the target
on specified one or more units
add-requires TARGET NAME... Add 'Requires' dependency for the target
on specified one or more units
edit NAME... Edit one or more unit files
get-default Get the name of the default target
set-default NAME Set the default target
Machine Commands:
list-machines [PATTERN...] List local containers and host
Job Commands:
list-jobs [PATTERN...] List jobs
cancel [JOB...] Cancel all, one, or more jobs
Snapshot Commands:
snapshot [NAME] Create a snapshot
delete NAME... Remove one or more snapshots
Environment Commands:
show-environment Dump environment
set-environment NAME=VALUE... Set one or more environment variables
unset-environment NAME... Unset one or more environment variables
import-environment [NAME...] Import all or some environment variables
Manager Lifecycle Commands:
daemon-reload Reload systemd manager configuration
daemon-reexec Reexecute systemd manager
System Commands:
is-system-running Check whether system is fully running
default Enter system default mode
rescue Enter system rescue mode
emergency Enter system emergency mode
halt Shut down and halt the system
poweroff Shut down and power-off the system
reboot [ARG] Shut down and reboot the system
kexec Shut down and reboot the system with kexec
exit Request user instance exit
switch-root ROOT [INIT] Change to a different root file system
suspend Suspend the system
hibernate Hibernate the system
hybrid-sleep Hibernate and suspend the system
# 列出正在運行的 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
# 查看 Unit 配置文件的內(nèi)容
$ systemctl cat docker.service
# 顯示系統(tǒng)狀態(tài)
$ systemctl status
# 顯示單個 Unit 的狀態(tài)
$ ystemctl status bluetooth.service
# 顯示遠程主機的某個 Unit 的狀態(tài)
$ systemctl -H root@rhel7.example.com status httpd.service
# 立即啟動一個服務
$ sudo systemctl start apache.service
# 立即停止一個服務
$ sudo systemctl stop apache.service
# 重啟一個服務
$ sudo systemctl restart apache.service
# 殺死一個服務的所有子進程
$ sudo systemctl kill apache.service
# 重新加載一個服務的配置文件
$ sudo systemctl reload apache.service
# 重載所有修改過的配置文件
$ sudo systemctl daemon-reload
# 顯示某個 Unit 的所有底層參數(shù)
$ systemctl show httpd.service
# 顯示某個 Unit 的指定屬性的值
$ systemctl show -p CPUShares httpd.service
# 設(shè)置某個 Unit 的指定屬性
$ sudo systemctl set-property httpd.service CPUShares=500
# 列出一個 Unit 的所有依賴,默認不會列出 target 類型
$ systemctl list-dependencies nginx.service
# 列出一個 Unit 的所有依賴,包括 target 類型
$ systemctl list-dependencies --all nginx.service
當一個新的 Unit 文件被放入 /etc/systemd/system/ 或 /usr/lib/systemd/system/ 目錄中時,它是不會被自識識別的。
Target 就是一個 Unit 組,包含許多相關(guān)的 Unit 。啟動某個 Target 的時候,Systemd 就會啟動里面所有的 Unit。
在傳統(tǒng)的 SysV-init 啟動模式里面,有 RunLevel 的概念,跟 Target 的作用很類似。不同的是,RunLevel 是互斥的,不可能多個 RunLevel 同時啟動,但是多個 Target 可以同時啟動。
# 查看當前系統(tǒng)的所有 Target
$ systemctl list-unit-files --type=target
# 查看一個 Target 包含的所有 Unit
$ systemctl list-dependencies multi-user.target
# 查看啟動時的默認 Target
$ systemctl get-default
# 設(shè)置啟動時的默認 Target
$ sudo systemctl set-default multi-user.target
# 切換 Target 時,默認不關(guān)閉前一個 Target 啟動的進程,systemctl isolate 命令改變這種行為,關(guān)閉前一個 Target 里面所有不屬于后一個 Target 的進程
$ sudo systemctl isolate multi-user.target
Systemd 通過其標準日志服務 Journald 提供的配套程序 journalctl 將其管理的所有后臺進程打印到 std:out(即控制臺)的輸出重定向到了日志文件。
Systemd 的日志文件是二進制格式的,必須使用 Journald 提供的 journalctl 來查看,默認不帶任何參數(shù)時會輸出系統(tǒng)和所有后臺進程的混合日志。
默認日志最大限制為所在文件系統(tǒng)容量的 10%,可以修改 /etc/systemd/journald.conf 中的 SystemMaxUse 來指定該最大限制。
# 查看所有日志(默認情況下 ,只保存本次啟動的日志)
$ sudo journalctl
# 查看內(nèi)核日志(不顯示應用日志):--dmesg 或 -k
$ sudo journalctl -k
# 查看系統(tǒng)本次啟動的日志(其中包括了內(nèi)核日志和各類系統(tǒng)服務的控制臺輸出):--system 或 -b
$ sudo journalctl -b
$ sudo journalctl -b -0
# 查看上一次啟動的日志(需更改設(shè)置)
$ sudo journalctl -b -1
# 查看指定服務的日志:--unit 或 -u
$ sudo journalctl -u docker.servcie
# 查看指定服務的日志
$ sudo journalctl /usr/lib/systemd/systemd
# 實時滾動顯示最新日志
$ sudo journalctl -f
# 查看指定時間的日志
$ sudo journalctl --since='2012-10-30 18:17:16'
$ sudo journalctl --since '20 min ago'
$ sudo journalctl --since yesterday
$ sudo journalctl --since '2015-01-10' --until '2015-01-11 03:00'
$ sudo journalctl --since 09:00 --until '1 hour ago'
# 顯示尾部的最新 10 行日志:--lines 或 -n
$ sudo journalctl -n
# 顯示尾部指定行數(shù)的日志
$ sudo journalctl -n 20
# 將最新的日志顯示在前面
$ sudo journalctl -r -u docker.service
# 改變輸出的格式:--output 或 -o
$ sudo journalctl -r -u docker.service -o json-pretty
# 查看指定進程的日志
$ sudo journalctl _PID=1
# 查看某個路徑的腳本的日志
$ sudo journalctl /usr/bin/bash
# 查看指定用戶的日志
$ sudo journalctl _UID=33 --since today
# 查看某個 Unit 的日志
$ sudo journalctl -u nginx.service
$ sudo journalctl -u nginx.service --since today
# 實時滾動顯示某個 Unit 的最新日志
$ sudo journalctl -u nginx.service -f
# 合并顯示多個 Unit 的日志
$ journalctl -u nginx.service -u php-fpm.service --since today
# 查看指定優(yōu)先級(及其以上級別)的日志,共有 8 級
# 0: emerg
# 1: alert
# 2: crit
# 3: err
# 4: warning
# 5: notice
# 6: info
# 7: debug
$ sudo journalctl -p err -b
# 日志默認分頁輸出,--no-pager 改為正常的標準輸出
$ sudo journalctl --no-pager
# 以 JSON 格式(單行)輸出
$ sudo journalctl -b -u nginx.service -o json
# 以 JSON 格式(多行)輸出,可讀性更好
$ sudo journalctl -b -u nginx.serviceqq
-o json-pretty
# 顯示日志占據(jù)的硬盤空間
$ sudo journalctl --disk-usage
# 指定日志文件占據(jù)的最大空間
$ sudo journalctl --vacuum-size=1G
# 指定日志文件保存多久
$ sudo journalctl --vacuum-time=1years
# 重啟系統(tǒng)
$ sudo systemctl reboot
# 關(guān)閉系統(tǒng),切斷電源
$ sudo systemctl poweroff
# CPU停止工作
$ sudo systemctl halt
# 暫停系統(tǒng)
$ sudo systemctl suspend
# 讓系統(tǒng)進入冬眠狀態(tài)
$ sudo systemctl hibernate
# 讓系統(tǒng)進入交互式休眠狀態(tài)
$ sudo systemctl hybrid-sleep
# 啟動進入救援狀態(tài)(單用戶狀態(tài))
$ sudo systemctl rescue
# 查看啟動耗時
$ systemd-analyze
# 查看每個服務的啟動耗時
$ systemd-analyze blame
# 顯示瀑布狀的啟動過程流
$ systemd-analyze critical-chain
# 顯示指定服務的啟動流
$ systemd-analyze critical-chain atd.service
# 顯示當前主機的信息
$ hostnamectl
# 設(shè)置主機名。
$ sudo hostnamectl set-hostname rhel7
# 查看當前時區(qū)設(shè)置
$ timedatectl
# 顯示所有可用的時區(qū)
$ timedatectl list-timezones
# 設(shè)置當前時區(qū)
$ sudo timedatectl set-timezone America/New_York
$ sudo timedatectl set-time YYYY-MM-DD
$ sudo timedatectl set-time HH:MM:SS
# 列出當前 session
$ loginctl list-sessions
# 列出當前登錄用戶
$ loginctl list-users
# 列出顯示指定用戶的信息
$ loginctl show-user ruanyf
$ PASSWORD=$(systemd-ask-password 'Input Your Passowrd:')
systemd-run 可以將一個指定的操作變成后臺運行的服務。它的效果似乎與直接在命令后加上表示后臺運行的 & 符號很相似。然而,它讓命令成為服務還意味著,它的生命周期將由 Systemd 控制。具體來說,包括以下好處:
來源:Mallux Blog 原文:https://tinyurl.com/yyp6jbta 題圖:來自谷歌圖片搜索 版權(quán):本文版權(quán)歸原作者所有 投稿:歡迎投稿,郵箱: editor@hi-linux.com
聯(lián)系客服