天天學五分鐘 Liunx 0110 | 服務篇:守護進程 systemd


有些進程會在系統上運行較長時間,如前面的 Hello World 程序運行時產生的進程。有些進程運行瞬間就結束了,如執行 ps 命令產生的進程,也有的進程會常駐在內存中,提供相應的服務,這樣的進程稱爲守護進程(daemon),它所提供的功能叫作服務。
 
這樣的守護進程有不少。好比,sshd(d 表示 daemon) 守護進程提供 ssh 登錄鏈接服務,crond 守護進程提供週期性處理任務服務,等等。
Liunx 也提供了一個爲系統啓動管理提供完整解決方案的守護進程 systemd。
 

systemd 

systemd 是系統啓動的第一個守護進程,相似於一個大管家,它爲系統啓動和管理提供了至關完整的服務。
傳統的 Liunx 發行版(CentOS5 / CentOS6)採用的是 init 進程做爲系統的啓動進程,它的缺點是啓動時間長(串行啓動,前一個進程啓動完才能啓動下一個進程)而且啓動腳本複雜,而 systemd 解決了這些問題。
systemd 的示意圖以下:
 
 

systemd 命令

systemd 是一組命令的集和,先列出經常使用的命令:
系統管理
systemctl
重啓系統
sudo systemctl reboot
暫停系統
sudo systemctl suspend
CPU 中止工做
sudo systemctl halt
關閉系統,切斷電源
sudo systemctl poweroff 
systemd-analyze
查看啓動耗時
systemd-analyze
查看每一個服務啓動耗時
systemd-analyze blame
查看啓動過程流
systemd-analyze critical-chain
查看指定服務的啓動流
systemd-analyze critical-chain sshd.service
hostnamectl
查看當前主機信息
hostnamectl
設置主機名
sudo hostnamectl set-hostname ***
localectl
查看本地化設置
localectl
timedatectl
查看當前時區設置
timedatectl
顯示全部可用時區
timedatectl list-timezones
設置當前時區
sudo timedatectl set-timezone Africa/Juba
Unit
systemctl list-units
查看系統正在運行的單元
systemctl list-units
列出系統中全部單元
systemctl list-units --all
列出全部加載失敗的單元
systemctl list-units --failed
列出全部正在運行,類型爲服務的單元
systemctl list-units --type=service
systemctl status
查看系統狀態
systemctl status
查看服務狀態
systemctl status ***.service
查看遠端主機的服務狀態
systemctl -H user@hostname status ***.service
unit 管理
啓動服務
sudo systemctl start ***.service
中止服務
sudo systemctl stop ***.service
重啓服務
sudo systemctl restart ***.service
殺死服務產生的全部子進程
sudo systemctl kill ***.service
從新加載服務配置文件
sudo systemctl reload ***.service
從新加載全部修改單元的配置文件
sudo systemctl daemon-reload
顯示 unit 的底層參數
sudo systemctl show ***.service
systemctl list-dependencies
列出服務的依賴關係
systemctl list-dependencies ***.service
列出服務的反向依賴關係
systemctl list-dependencies --reverse ***.service
查看 target 包含的 unit
systemctl list-dependencies ***.target
unit 配置文件
查看 unit 配置文件的內容
systemctl cat ***.service
查看全部配置文件
systemctl list-unit-files
查看指定類型的配置文件
systemctl list-unit-files --type=service
Target
查看系統的全部 target
systemctl list-unit-files --type=target
查看 target 包含的 unit
systemctl list-dependencies ***.target
查看啓動時的默認 target
systemctl get-default
日誌管理
journalctl
查看本次系統啓動的全部日誌
journalctl 
查看指定 Unit 的日誌
journalctl -u ***.service
滾動顯示最新的日誌
journalctl -f
查看指定時間的日誌
journalctl --since "2020-05-06 01:00" --until "2020-05-06 03:00"
 
簡單介紹個比較重要的命令 systemd-analyze ciritical-chain :
[root@lianhua ~]$ systemd-analyze critical-chain sshd.service
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.
 
sshd.service +16ms
└─cloud-init.service @6.503s +9.732s
  └─network.service @3.352s +3.121s
    └─network-pre.target @3.348s
      └─cloud-init-local.service @1.665s +1.682s
        └─dbus.socket @1.659s
          └─sysinit.target @1.628s
            └─systemd-update-utmp.service @1.614s +13ms
              └─auditd.service @1.424s +182ms
                └─systemd-tmpfiles-setup.service @1.394s +16ms
                  └─rhel-import-state.service @1.341s +40ms
                    └─local-fs.target @1.325s
                      └─ephemeral.mount @747ms +577ms
                        └─local-fs-pre.target @728ms
                          └─lvm2-monitor.service @368ms +359ms
                            └─lvm2-lvmetad.service @484ms
                              └─lvm2-lvmetad.socket @329ms
                                └─-.slice
 
輸出結果中,"@" 後面的時刻表示該單元的啓動時刻; "+"後面的時長表示該單元總計花了多長時間才完成啓動。須要注意的是, 這些信息可能具備誤導性, 由於花費較長時間啓動的單元, 有可能只是在等待另外一個依賴單元完成啓動,服務在啓動時並非按順序啓動的。
 

Unit

systemd 管理的多個系統資源統稱爲 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:定時器
 
查看 sshd 這個 service unit 的狀態:
[root@lianhua ~]$ systemctl status sshd.service
● sshd.service - OpenSSH server daemon
   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2019-11-01 18:35:20 CST; 6 months 3 days ago
     Docs: man:sshd(8)
           man:sshd_config(5)
Main PID: 8621 (sshd)
   Memory: 24.7M
   CGroup: /system.slice/sshd.service
           └─8621 /usr/sbin/sshd -D
 
Nov 01 18:35:20 lianhua systemd[1]: Starting OpenSSH server daemon...
 
查看啓動 sshd.service 須要依賴的 unit:
[root@lianhua ~]$ systemctl list-dependencies sshd.service
sshd.service
● ├─sshd-keygen.service
● ├─system.slice
● └─basic.target
●   ├─microcode.service
●   ├─rhel-dmesg.service
●   ├─selinux-policy-migrate-local-changes@targeted.service
...
 
查看哪些 unit 須要依賴 sshd.service:
[root@lianhua ~]$ systemctl list-dependencies --reverse sshd.service
sshd.service
● ├─cloud-init.service
● └─multi-user.target
●   └─graphical.target
 
查看 sshd.service 的配置文件:
[root@lianhua ~]$ 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]
Type=notify
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,Service 和 Install,每塊參數介紹以下:
[Unit]
Description:對 Unit 進行簡單描述的字符串。
Documentation:對 Unit 詳細說明的文檔。
After:強調單元間的啓動前後順序,After 是在後面指定單元以後啓動。
Before:對應於 After,強調單元間的前後順序,在後面指定單元以前啓動。
Requires:設置單元間的依賴關係,注意 After 和 Before 只強調了啓動順序,並無設置依賴關係。Requires 設置單元強依賴指定的單元,若是指定單元啓動失敗,將不會啓動該單元。
Wants:弱依賴關係,指定的 Unit 若是啓動失敗當前 Unit 仍是會啓動。
BindsTo: 與 Requires 相似,可是依賴性更強。在 Requires 中被依賴單元若是條件檢查失敗或者單元主動中止,並不會使得依賴單元也跟着一塊兒中止,使用 BindsTo 就能實現若是被依賴單元中止,依賴單元跟着會中止。
Conflicts:指定單元間的衝突關係,若是指定的單元啓動,當前單元將不會啓動,當前單元啓動則指定的單元必須中止。
 
[Service]
Unit 執行的主體。
Type: 設置進程的啓動類型,必須設爲 simple,exec,forking,oneshot,dbus,notify 和 idle:
  • simple:默認值,使用主進程執行 ExecStart 指定的命令。
  • forking:以 fork 的方式從父進程中建立子進程,建立後父進程當即退出。
  • oneshot:一次性進程,systemd 等待當前服務退出,再往下執行。
  • dbus:當前服務經過 D-Bus 啓動。
  • notify:當前服務啓動完畢,通知 systemd ,再繼續往下執行。
  • idle: 如有其它服務執行完畢,當前服務纔會運行。
ExecStart:啓動當前服務的命令。
EnvironmentFile:當前服務的環境配置文件,ExecStart 中的變量 $OPTIONS 即來自該配置文件。
ExecReload:當前服務從新載入配置時須要執行 ExecReload 指定的命令行,其中,$MAINPID 是個特殊的環境變量,它表示主進程的 PID。
KillMode:設置在單元中止時,殺死進程的方法。process 表示僅殺死主進程。
Restart:當服務進程正常退出,異常退出,被殺死,超時的時候是否重啓該服務。on-failue 表示僅在服務異常退出時重啓該服務。
RestartSec:設置服務重啓前暫停多長時間,默認單位爲 s。
 
[Install]
Install 用來定義 Unit 如何啓動,以及是否開機自啓動。
WantedBy:在使用 systemctl enable 啓用此單元時, 將會在每一個列表單元的 .wants/ 目錄中建立一個指向該單元文件的軟鏈接。至關於爲每一個列表中的單元文件添加 Wants= 單元選項。 這樣當列表中的任意一個單元啓動時,該單元都會被啓動。
RequiredBy:相似於 WantedBy 至關於添加 Requires= 單元選項。
 

Unit 配置文件狀態

 
Systemd 默認從目錄 /etc/systemd/system/ 讀取 Unit 的配置文件。可是,裏面存放的大部分文件都是符號連接,指向目錄/usr/lib/systemd/system/,真正的配置文件存放在這個目錄。若是兩個目錄之間創建了符號連接則表示該 Unit 創建了啓動連接。
 
命令 systemctl list-unit-files 能夠 show 出各 Unit 配置文件的狀態:
[root@lianhua ~]$ systemctl list-unit-files
UNIT FILE                                     STATE
tmp.mount                                     disabled
brandbot.path                                 enabled
auth-rpcgss-module.service                    static
autofs.service                                disabled
systemd-timedated.service                     masked
...
 
Unit 文件的狀態有四種:
enabled:已創建啓動連接;
disabled:未創建啓動連接,可是 Install 區塊中有能夠創建啓動連接的值;
masked:該 Unit 配置文件被禁止創建啓動連接,對應的是 /etc/systemd/system/ 目錄軟連接指向了 /dev/null;
static:該配置文件沒有 Install 部分,只能做爲其它 Unit 的依賴被啓用;
 
分別查看四種狀態下的文件配置信息:
# autofs.service disabled
[root@lianhua ~]# systemctl cat autofs.service
# /usr/lib/systemd/system/autofs.service
[Unit]
...
[Service]
...
[Install]
WantedBy=multi-user.target
[root@lianhua ~]# ll /etc/systemd/system/multi-user.target.wants/ | grep autofs.service
[root@lianhua ~]#
 
# brandbot.path enabled
[root@lianhua ~]$ systemctl cat brandbot.path
# /usr/lib/systemd/system/brandbot.path
[Unit]
...
[Path]
...
[Install]
WantedBy=multi-user.target
[root@lianhua ~]$ ll /etc/systemd/system/multi-user.target.wants/ | grep brand
lrwxrwxrwx. 1 root root 37 May  9  2018 brandbot.path -> /usr/lib/systemd/system/brandbot.path

 
# systemd-timedated.service masked
[root@lianhua ~]# ll /etc/systemd/system | grep systemd-timedated.service
lrwxrwxrwx. 1 root root    9 Aug 12  2018 systemd-timedated.service -> /dev/null
 
 
# auth-rpcgss-module.service static
[root@lianhua ~]# systemctl cat auth-rpcgss-module.service
[Unit]
...
[Service]
...
 
命令 systemctl enable 和 systemctl diable 分別能夠給 Unit 創建啓動連接(前提是它們能夠被創建啓動連接) 和撤銷啓動連接,命令 systemctl is-enable 能夠查看 Unit 是否是 enable 的,舉例:
[root@lianhua ~]# systemctl is-enabled autofs.service
disabled
[root@lianhua ~]# systemctl enable autofs.service
Created symlink /etc/systemd/system/multi-user.target.wants/autofs.service → /usr/lib/systemd/system/autofs.service.
[root@lianhua ~]# systemctl is-enabled autofs.service
enabled
 
 
除了命令查看 Unit 是否 enable 以外,還有一種經過 systemctl status 查看 Unit 是否 enable 的方法:
[root@lianhua ~]# systemctl status autofs.service
● autofs.service - Automounts filesystems on demand
   Loaded: loaded (/usr/lib/systemd/system/autofs.service; enabled; vendor preset: disabled)
   Active: inactive (dead)
 
第一行 Loaded 的第一個 enabled 表示當前 Unit 是否開機自啓動,也就是 systemctl is-enable 要 show 的值。
第二個 disabled 表示 systemd 預設(preset)文件中是否默認啓用(enable)或停用(disable) Unit。能夠從如下目錄中來查看 Unit 的預設文件:
/etc/systemd/system-preset/*.preset
/run/systemd/system-preset/*.preset
/usr/lib/systemd/system-preset/*.preset
/etc/systemd/user-preset/*.preset
/run/systemd/user-preset/*.preset
/usr/lib/systemd/user-preset/*.preset
 
舉例:
[root@lianhua ~]# ll /usr/lib/systemd/system-preset/
total 24
-rw-r--r--. 1 root root  264 Sep 25  2019 85-display-manager.preset
-rw-r--r--. 1 root root 3982 Sep 25  2019 90-default.preset
-rw-r--r--. 1 root root  951 Jun 22  2018 90-systemd.preset
 
[root@lianhua ~]# cat /usr/lib/systemd/system-preset/90-systemd.preset
enable remote-fs.target
disable console-getty.service
disable debug-shell.service
 
預設文件的格式是 「優先級-策略名.preset」,其中優先級數字越小表示優先級越高。通常軟件包自帶的預設文件應放到 /usr/lib 目錄下,系統管理員設定的預設文件放在 /etc 目錄下, 對於不一樣目錄下的同名預設文件僅以優先級最高的目錄中的那一個爲準,即 /etc/ 的優先級最高、 /run/ 的優先級居中、 /usr/lib/ 的優先級最低。
預設文件的內容 enable 表示默認啓用指定的 Unit,disable 表示默認停用指定的單元。
 
 
如今試想一種狀況,若是 service(unit) 的配置文件都寫好了,可是須要臨時改動執行 service 的 user ,這時候須要從新寫配置文件嗎?
答案是不須要,能夠經過 systemd 的 Drop-in 機制從新更改 Unit 的配置,好比:
[root@lianhua process]$ systemctl status autofs.service
● autofs.service - Automounts filesystems on demand
   Loaded: loaded (/usr/lib/systemd/system/autofs.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-08-05 17:42:46 CST; 9 months 0 days ago
  Process: 23921 ExecReload=/usr/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
 
[root@lianhua process]$ cat /usr/lib/systemd/system/autofs.service.d/app.conf
[Service]
User=
User=app
[root@lianhua process]$ systemctl daemon-reload
[root@lianhua process]$ systemctl restart autofs.service
[root@lianhua process]$ systemctl status autofs.service
● autofs.service - Automounts filesystems on demand
   Loaded: loaded (/usr/lib/systemd/system/autofs.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/autofs.service.d
           └─app.conf
   Active: active (running) since Mon 2019-08-05 17:42:46 CST; 9 months 0 days ago
 
systemd 中使用 Drop-in 機制須要在 unit 的同級目錄下建 ***.d 的目錄,目錄下配置以 .conf 結尾的文件。
文件中第一行表示更改的配置塊,第一個 User= 表示取消服務執行的用戶,第二個 User 表示將服務執行的用戶指定爲給定值,示例中配置的是 app 這個用戶。
配置完以後,須要從新加載 systemd 的配置文件,而後重啓相關 unit,檢查 unit 的狀態發現多了一個 Drop-In 文件,而且狀態時 active 的。
 

Target

Target 是一類特殊的 Unit,它表示一個 Unit 組,systemd 在啓動 Target 的時候,會啓動 Target 包含的全部 Unit。因此 systemd 啓動到某個 target 至關因而啓動到了某個狀態。
查看 target 狀態:
[root@lianhua ~]# systemctl cat cloud-config.target
[Unit]
Description=Cloud-config availability
Wants=cloud-init-local.service cloud-init.service
After=cloud-init-local.service cloud-init.service
[root@lianhua ~]# systemctl status cloud-config.target
● cloud-config.target - Cloud-config availability
   Loaded: loaded (/usr/lib/systemd/system/cloud-config.target; static; vendor preset: disabled)
   Active: active since Fri 2020-03-13 09:18:36 UTC; 1 months 22 days ago
 

path unit

[root@lianhua ~]# systemctl status systemd-ask-password-wall.path
● systemd-ask-password-wall.path - Forward Password Requests to Wall Directory Watch
   Loaded: loaded (/usr/lib/systemd/system/systemd-ask-password-wall.path; static; vendor preset: disabled)
   Active: active (waiting) since Fri 2020-03-13 09:17:52 UTC; 1 months 22 days ago
     Docs: man:systemd-ask-password-console.service(8)
 
[root@lianhua ~]# systemctl cat systemd-ask-password-wall.path
[Unit]
Description=Forward Password Requests to Wall Directory Watch
...
 
[Path]
DirectoryNotEmpty=/run/systemd/ask-password
MakeDirectory=yes
[root@lianhua ~]# systemctl status systemd-ask-password-wall
● systemd-ask-password-wall.service - Forward Password Requests to Wall
   Loaded: loaded (/usr/lib/systemd/system/systemd-ask-password-wall.service; static; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:systemd-ask-password-console.service(8)
 
path 也是衆多 unit 的一種,它是 systemd 用來監視文件系統路徑,以支持基於路徑啓動的單元。
每一個路徑單元都必須有一個與其匹配的單元,以用於在路徑發生變化時啓動。匹配的單元能夠經過 Unit= 選項明確指定。若未指定,則默認是與該單元名稱相同的 .service 單元(不算後綴)。例如 systemd-ask-password-wall.path 默認匹配 systemd-ask-password-wall.service 單元。
<path 的具體參數配置可看這裏>
 

mount unit

若是一個 path 單元的文件系統路徑位於另外一個 mount 單元之下, 那麼將會自動得到對其所依賴的掛載點單元的 Requires= 與 After= 依賴。
mount 一樣的是衆多 unit 的一種,它是 systemd 用來管理文件系統掛載點的單元。
[root@lianhua process]$ systemctl status build.mount
● build.mount - /build
   Loaded: loaded (/etc/fstab; bad; vendor preset: disabled)
   Active: active (mounted) since Mon 2019-08-05 17:42:44 CST; 9 months 0 days ago
    Where: /build
     What: lianhua.net:/vol/test/build/build
     Docs: man:fstab(5)
           man:systemd-fstab-generator(8)
   Memory: 0B
 
Aug 05 17:42:44 lianhua systemd[1]: Mounting /build...
Aug 05 17:42:44 lianhua systemd[1]: Mounted /build.
[root@lianhua process]$ systemctl cat build.mount
 
[Unit]
SourcePath=/etc/fstab
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
Before=remote-fs.target
 
[Mount]
What=lianhua.net:/vol/test/build/build
Where=/build
Type=nfs
Options=soft,intr,retry=1,rw,rsize=32768,wsize=32768
[root@lianhua process]$ df -hT | grep /build
lianhua.net:/vol/test/build/build nfs        21T   17T  4.3T  80% /build
 
mount 單元中,參數 where 表示掛載點目錄,須要指明絕對路徑,參數 what 表示被掛載對象,一樣須要指明絕對路徑。參數 type 表示掛載的文件系統類型。
 
 
 
(完)
相關文章
相關標籤/搜索