Linux服務管理神器:SYSTEMD介紹

筆者在平常的開發和使用中,常常須要寫大量的本地服務而且進行管理,例如定時執行,定時查錯,異步排隊以及數據庫的備份歸檔工做。所以systemd做爲一個服務管理神器就成了必備工具。今天就寫一篇小工具文來介紹一下這東西的用法。shell

1、SYSTEMD基本工具

監控和控制systemd主要使用的指令是systemctl。主要是歷來看系統狀態、服務狀態,以及管理系統和服務。 同時systemctl能夠經過ssh鏈接遠程控制其餘主機,使用 systemctl -H <username>@<URL> 格式。數據庫

一、分析系統狀態

顯示系統狀態: $ systemctl status 輸出激活的單元列表: $systemctl 或者 $systemctl list-units 輸出運行失敗的單元: $ systemctl —failed緩存

全部可用的單元都在 /etc/systemd/system/(優先度高) 和 /usr/lib/systemd/system/(優先度低)。 查看全部已安裝的服務:$ systemctl list-unit-filesbash

二、使用單元

一個單元配置文件能夠描述以下內容之一:系統服務(.service)、掛載點(.mount)、sockets(.sockets) 、系統設備(.device)、交換分區(.swap)、文件路徑(.path)、啓動目標(.target)、由 systemd 管理的計時器(.timer)。服務器

咱們一般在用systemctl調用單元的時候通常要單元文件的全名。也就是帶上述後綴的那些。 若是不帶擴展名的話systemctl會默認成是.service文件,因此爲了避免發生意外通常仍是推薦把名字打全了。 掛載點和設備會自動轉化爲對應的後綴單元,好比/home就等價於home.mount, /dev/sda等價於dev-sda.device網絡

systemctl在enable、disable、mask子命令裏面增長了--now選項,能夠激活同時啓動服務,激活同時中止服務等。ssh

馬上激活單元:$ systemctl start <unit> 馬上中止單元:$ systemctl stop <unit> 重啓單元:$ systemctl restart <unit> 從新加載配置:$ systemctl reload <unit> 輸出單元運行的狀態:$ systemctl status <unit> 檢測單元是否爲自動啓動:$ systemctl is-enabled <unit> 設置爲開機自動激活單元:$ systemctl enable <unit> 設置爲開機自動激活單元並如今馬上啓動:$ systemctl enable --now <unit> 取消開機自動激活單元:$ systemctl disable <unit> 禁用一個單元:$ systemctl mask <unit> 取消禁用一個單元:$ systemctl unmask <unit> 顯示單元的手冊頁(前提是由unit提供):$ systemctl help <unit> 從新載入整個systemd的系統配置並掃描unit文件的變更:$ systemctl daemon-reload異步

三、電源管理

注意:須要安裝了polkit之後才能用普通用戶身份進行電源管理。socket

重啓:$ systemctl reboot 退出系統並關閉電源:$ systemctl poweroff 待機:$ systemctl suspend 休眠:$ systemctl hibernate 混合休眠模式:$ systemctl hybrid-sleep編輯器

2、編寫unit文件

systemd的unit書寫語法來源於XDG桌面配置文件,最初則來自於ini文件。 經過指令 $ systemctl show --property=UnitPath能夠按照優先級查看unit加載目錄。 /usr/lib/systemd/system/:軟件包安裝的單元 /etc/systemd/system/ :系統管理員安裝的單元

一、處理依賴關係

主要有三類之外關係處理配置: Requires=B:啓動必須依賴單元B Wants=B:啓動依賴單元B(可選) After=B:本單元在B運行後再運行

注意的是Requires和Want並無包含After屬性,若是不聲明After則默認同時啓動。

二、服務類型

Type=simple :(默認值) systemd認爲該服務將當即啓動。服務進程不會 fork 。 Type=forking :systemd認爲當該服務進程fork,且父進程退出後服務啓動成功。使用此啓動類型應同時指定 PIDFile=,以便 systemd 可以跟蹤服務的主進程。 Type=oneshot :這一選項適用於只執行一項任務、隨後當即退出的服務。可能須要同時設置 RemainAfterExit=yes 使 systemd 在服務進程退出以後仍然認爲服務處於激活狀態。 Type=notify :與 Type=simple 相同,但約定服務會在就緒後向 systemd 發送一個信號。 Type=dbus :若以此方式啓動,當指定的 BusName 出如今DBus系統總線上時,systemd認爲服務就緒。 Type=idle :systemd會等待全部任務處理完成後,纔開始執行 idle 類型的單元。其餘行爲與 Type=simple 相似。

三、修改現有的unit

直接修改文件並加載:$ systemctl daemon-reload 若是須要替換unit文件,則從新啓用單元:$ systemctl reenable <unit> 或者運行:$ systemctl edit --full unit

附加配置片斷:$ systemctl edit <unit> 這個操做會在編輯器裏面打開/etc/systemd/system/<unit>.d/override.conf

重置到軟件包版本:$ systemctl revert <unit>

3、目標 Target

目標是一個相似於運行界別的概念。一些目標能繼承其餘目標的服務而且啓動新的服務,systemd默認提供了一部分相似於sysvinit運行級別的target。

獲取當前的target:$ systemctl list-units --type=target 建立自定義target:咱們能夠新建一個/etc/systemd/system/.target。而後再建立目錄/etc/systemd/system/.want,而且在裏面加入須要啓動的服務器鏈接(指向/usr/lib/systemd/system/)

SysV Level Systemd 目標 註釋
0 runlevel0.target, poweroff.target 中斷系統(halt)
1, s, single runlevel1.target, rescue.target 單用戶模式
2, 4 runlevel2.target, runlevel4.target, multi-user.target 用戶自定義運行級別,一般識別爲級別3。
3 runlevel3.target, multi-user.target 多用戶,無圖形界面。用戶能夠經過終端或網絡登陸。
5 runlevel5.target, graphical.target 多用戶,圖形界面。繼承級別3的服務,並啓動圖形界面服務。
6 runlevel6.target, reboot.target 重啓
emergency emergency.target 急救模式(Emergency shell)

切換當前運行目標:$ systemctl isolate <target>.target 這個指令僅僅改變當前運行的target,不會對啓動有影響

更改開機默認啓動target: 檢查當前的啓動target:$ systemctl get-default 用systemctl修改default.target來變動開機啓動target:$ systemctl set-default multi-user.target

4、臨時文件

/usr/lib/tmpfiles.d//etc/tmpfiles.d/ 中的文件描述了 systemd-tmpfiles 如何建立、清理、刪除臨時文件和目錄,這些文件和目錄一般存放在 /run/tmp 中。配置文件名稱爲 /etc/tmpfiles.d/<program>.conf。此處的配置能覆蓋 /usr/lib/tmpfiles.d/ 目錄中的同名配置。

臨時文件通常和服務文件同時提供,來生成守護進程須要的文件和目錄。也能夠在開機的時候往特定的文件寫入一些內容。

5、定時器

一、服務單元

定時器是一個以.timer爲結尾的unit配置文件,包含了systemd控制和監督的信息。不少時候能夠替代crontab而且有更強的功能。 每個.timer文件在同一個目錄都有一個對應的.service文件。.timer用來激活並控制.service文件。.service文件不須要有[Install],這部分由.timer單元管理。

二、管理

使用.timer的方法也和其餘unit同樣,enable或者start便可。 查看已有的定時器使用:$ systemctl list-timers 查看全部的定時器(包括非活動的):$ systemctl list-timers --all

三、示例

下面是兩個timer單元的例子。

單調定時器:

/etc/systemd/system/example.timer
----------------------------------
[Unit]
Description=Run example weekly and on boot        ## 文件描述
[Timer]
OnBootSec=15min                                   ## 開機後多久啓動
OnUnitActiveSec=1w                                ## 執行間隔t
[Install]
WantedBy=timers.target                            ## 目標service單元
複製代碼

實時定時器: 定義一個定時執行,且上次未執行就馬上執行的timer

/etc/systemd/system/foo.timer
-----------------------------------
[Unit]
Description=Run foo weekly

[Timer]
OnCalendar=weekly
Persistent=true     
 
[Install]
WantedBy=timers.target
複製代碼
四、替代crontab探討

優點主要在於,每一個任務都有本身的systemd服務。從而:

  • 任務能夠獨立於定時器,便於測試。
  • 任務能夠運行在特殊狀況下。
  • 任務可使用cgroups的特性。
  • 任務能夠依賴於其餘systemd unit。
  • 任務記錄在systemd日誌裏,便於調試排查。

同時也能夠和crontab同樣在unit失效的時候發送一個email。不過如今通常都用其餘開源監控工具,更好用。

6、掛載

由於systemd也負責按 /etc/fstab 掛在目錄,因此在系統重啓或者從新加載系統管理器的時候,systemd-fstab-generator會把/etc/fstab裏面的配置轉化爲systemd unit。這些設置具體來講由 x-systemd組件來配置。

7、日誌

systemd提供了本身的日至系統。 讀取日誌:$ journalctl

默認狀況下(當 Storage= 在文件 /etc/systemd/journald.conf 中被設置爲 auto),日誌記錄將被寫入 /var/log/journal/。該目錄是 systemd 軟件包的一部分。

一、優先級

日誌系統內有日誌的優先級區分,下面爲對應介紹:

優先級 介紹
優先級0 Emergency(emerg)
優先級1 Alert(alert)
優先級2 Critical(crit)
優先級3 Error(err)
優先級4 Warning(warning)
優先級5 Notice(notice)
優先級6 Informational(info)
優先級7 Debug(debug)
二、功能

在日誌系統中,各個日誌都會用編碼來指代必定的功能區域。下面爲對應介紹:

編碼 內容(縮寫)
功能編碼0 kernel-message(kern)
功能編碼1 user-level-message(user)
功能編碼2 mail-system(mail)
功能編碼3 system-daemon(daemon)
功能編碼4 authorization-messages(auth)
功能編碼5 syslog(syslog)
功能編碼6 line-printer-subsystem(lpr)
功能編碼7 network-news-subsystem(news)
功能編碼8 uucp-subsystem(uucp)
功能編碼9 clock-daemon
功能編碼10 authpriv(authpri)
功能編碼11 ftp-daemon(ftp)
功能編碼12 tp-subsyst
功能編碼13 log-audit
功能編碼14 log-alert
功能編碼15 crontab(cron)
功能編碼16-23 local0-7
三、過濾輸出

Journalctl能夠過濾字段輸出,下面爲經常使用操做。

顯示本次啓動後全部日誌:$ journalctl -b 或者 $ journalctl -b -0 顯示上次啓動後的日誌:$ journalctl -b -1 顯示上上次啓動後的日誌:$ journalctl -b -2 只顯示錯誤衝突和重要告警信息:$ journalctl -p err..alert 或者用編號表示 $ journalctl -p 3..1 顯示某個時間開始的消息:$ journalctl --since="2019-01-01 00:00:00" 顯示最新的消息:$ journalctl -f 顯示特定程序的全部消息:$ journalctl /usr/lib/systemd/systemd 顯示某進程的全部信息:$ journalctl _PID=12345 顯示指定unit的全部信息:$ journalctl -u mydumper-archive.service 指定內核緩存消息:$ journalctl -k 顯示auth.log當前量:$ journalctl -f -1 SYSLOG_FACILITY=10

四、日誌大小限制

默認狀況下,systemd日誌的最大限制是所在FS容量的10%。可是咱們能夠經過修改來改變最大限制:

/etc/systemd/journald.conf
--------------------------------
SystemMaxUse=50M
複製代碼

同時也能夠經過配置片斷而非全局來進行設置:

/etc/systemd/journald.conf.d/00-journal-size.conf
-----------------------------------
[Journal]
SystemMaxUse=50M
複製代碼
五、配合syslog

systemd提供了socket:/run/systemd/journal/syslog,來兼容傳統日誌服務。若是要讓傳統的日誌服務工做,則要用這個socket來替代/dev/log。若是是使用rsyslog,則不用更改。

設置開機啓動syslog-ng:$ systemctl enable syslog-ng

六、清理日誌

全部的日誌都存放在/var/log/journal,這個目錄下其實rm也能夠用來清理,可是不推薦。 下面的方法比較推薦。 清理日誌到小於100MB:$ journalctl --vacuum-size=100M 清理最先兩週前的日誌:$ journalctl --vacuum-time=2weeks

8、疑難和差錯

一、尋找錯誤

這個案例中咱們以mydumper-ro.service爲例 經過systemd尋找失敗的服務:$ systemctl --state=failed 或者用systemd消息:$ journalctl -fp err 找到了錯誤unit後查看更多信息:$ systemctl status mydumper-ro 查到這個unit的PID是12345以後:$ journalctl -b _PID=12345 發現部份內核模塊的配置文件有問題:$ ls -Al /etc/mydumper-ro.d 修復錯誤,最後從新啓動服務便可。

二、診斷啓動問題

在配置中使用內核參數引導:systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M

三、診斷一個服務

在服務的配置文件中加入診斷選項。

[Service]
Environment=SYSTEMD_LOG_LEVEL=debug
複製代碼
四、短運行時間進程無日誌

有時候某些短期進程沒有任何輸出,沒有日誌。這個時候應該使用PID來查詢。

五、禁止程序崩潰是轉儲內存

須要使用舊的內存轉儲則在對應的服務的配置文件中加入下面的設置:

/etc/sysctl.d/49-coredump.conf
-----------------------------------
kernel.core_pattern = core
kernel.core_uses_pid = 0
複製代碼
相關文章
相關標籤/搜索