CentOS 7 使用systemd替換了SysV。Systemd目的是要取代Unix時代以來一直在使用的init系統,兼容SysV和LSB的啓動腳本,並且夠在進程啓動過程當中更有效地引導加載服務。php
systemd的特性有:html
- 支持並行化任務
- 同時採用socket式與D-Bus總線式激活服務;
- 按需啓動守護進程(daemon);
- 利用 Linux 的 cgroups 監視進程;
- 支持快照和系統恢復;
- 維護掛載點和自動掛載點;
- 各服務間基於依賴關係進行精密控制。
systemd基本工具
檢視和控制systemd的主要命令是systemctl。該命令可用於查看系統狀態和管理系統及服務。詳見man 1 systemctl。前端
小貼士:linux
- 在 systemctl 參數中添加 -H <用戶名>@<主機名> 能夠實現對其餘機器的遠程控制。該過程使用ssh連接。
- systemadm是systemd 的官方圖形前端
分析系統狀態
輸出激活的單元:web
- $ systemctl
如下命令等效:shell
- $ systemctl list-units
輸出運行失敗的單元:vim
- $ systemctl --failed
全部可用的單元文件存放在 /usr/lib/systemd/system/ 和 /etc/systemd/system/ 目錄(後者優先級更高)。查看全部已安裝服務:網絡
- $ systemctl list-unit-files
使用單元
一個單元配置文件能夠描述以下內容之一:系統服務(.service)、掛載點(.mount)、sockets(.sockets) 、系統設備(.device)、交換分區(.swap)、文件路徑(.path)、啓動目標(.target)、由 systemd 管理的計時器(.timer)。詳情參閱 man 5 systemd.unit。ssh
使用 systemctl 控制單元時,一般須要使用單元文件的全名,包括擴展名(例如 sshd.service)。可是有些單元能夠在systemctl中使用簡寫方式。socket
- 若是無擴展名,systemctl 默認把擴展名看成 .service。例如 netcfg 和 netcfg.service 是等價的。
- 掛載點會自動轉化爲相應的 .mount 單元。例如 /home 等價於 home.mount。
- 設備會自動轉化爲相應的 .device 單元,因此 /dev/sda2 等價於 dev-sda2.device。
注: 有一些單元的名稱包含一個 @ 標記, (e.g. name@string.service): 這意味着它是模板單元 name@.service 的一個 實例。 string 被稱做實例標識符, 在 systemctl 調用模板單元時,會將其看成一個參數傳給模板單元,模板單元會使用這個傳入的參數代替模板中的 %I 指示符。 在實例化以前,systemd 會先檢查 name@string.suffix 文件是否存在(若是存在,應該就是直接使用這個文件,而不是模板實例化了)。大多數狀況下,包換 @ 標記都意味着這個文件是模板。若是一個模板單元沒有實例化就調用,該調用會返回失敗,由於模板單元中的 %I 指示符沒有被替換。
當即激活單元:
- # systemctl start <單元>
當即中止單元:
- # systemctl stop <單元>
重啓單元:
- # systemctl restart <單元>
命令單元從新讀取配置:
- # systemctl reload <單元>
輸出單元運行狀態:
- $ systemctl status <單元>
檢查單元是否配置爲自動啓動:
- $ systemctl is-enabled <單元>
開機自動激活單元:
- # systemctl enable <單元>
注意: 若是服務沒有Install段落,通常意味着應該經過其它服務自動調用它們。若是真的須要手動安裝,能夠直接鏈接服務,以下(將foo替換爲真實的服務名):
- # ln -s /usr/lib/systemd/system/foo.service /etc/systemd/system/graphical.target.wants/
取消開機自動激活單元:
- # systemctl disable <單元>
顯示單元的手冊頁(必須由單元文件提供):
- # systemctl help <單元>
從新載入 systemd,掃描新的或有變更的單元:
- # systemctl daemon-reload
電源管理
安裝 polkit 後纔可以使用電源管理。
若是你正登陸在一個本地的systemd-logind用戶會話,且當前沒有其它活動的會話,那麼如下命令無需root權限便可執行。不然(例如,當前有另外一個用戶登陸在某個tty),systemd 將會自動請求輸入root密碼。
重啓:
- $ systemctl reboot
退出系統並中止電源:
- $ systemctl poweroff
待機:
- $ systemctl suspend
休眠:
- $ systemctl hibernate
混合休眠模式(同時休眠到硬盤並待機):
- $ systemctl hybrid-sleep
編寫單元文件
systemd單元文件的語法來源於 XDG桌面入口配置文件.desktop文件,最初的源頭則是Microsoft Windows的.ini文件。單元文件能夠從兩個地方加載,優先級從低到高分別是:
- /usr/lib/systemd/system/: 軟件包安裝的單元
- /etc/systemd/system/: 系統管理員安裝的單元
注意: 當systemd運行在用戶模式下時,使用的加載路徑是徹底不一樣的。
單元文件的語法,能夠參考系統已經安裝的單元,也能夠參考man systemd.service中的EXAMPLES章節。
小貼士: 以 # 開頭的註釋可能也能用在 unit-files 中, 可是隻能在新行中使用。 不要在 systemd 的參數後面使用行末註釋, 不然 unit 將會啓動失敗。
處理依賴關係
使用systemd時,可經過正確編寫單元配置文件來解決其依賴關係。典型的狀況是,單元A要求單元B在A啓動以前運行。在此狀況下,向單元A配置文件中的 [Unit] 段添加 Requires=B 和 After=B 便可。若此依賴關係是可選的,可添加 Wants=B 和 After=B。請注意 Wants= 和 Requires= 並不意味着 After=,即若是 After= 選項沒有制定,這兩個單元將被並行啓動。
依賴關係一般被用在服務(service)而不是目標(target)上。例如, network.target 通常會被某個配置網絡接口的服務引入,因此,將自定義的單元排在該服務以後便可,由於 network.target 已經啓動。
服務類型
編寫自定義的 service 文件時,能夠選擇幾種不一樣的服務啓動方式。啓動方式可經過配置文件 [Service] 段中的 Type= 參數進行設置。
- Type=simple(默認值):systemd認爲該服務將當即啓動。服務進程不會fork。若是該服務要啓動其餘服務,不要使用此類型啓動,除非該服務是socket激活型。
- Type=forking:systemd認爲當該服務進程fork,且父進程退出後服務啓動成功。對於常規的守護進程(daemon),除非你肯定此啓動方式沒法知足需求,使用此類型啓動便可。使用此啓動類型應同時指定 PIDFile=,以便systemd可以跟蹤服務的主進程。
- Type=oneshot:這一選項適用於只執行一項任務、隨後當即退出的服務。可能須要同時設置 RemainAfterExit=yes 使得 systemd 在服務進程退出以後仍然認爲服務處於激活狀態。
- Type=notify:與 Type=simple 相同,但約定服務會在就緒後向 systemd 發送一個信號。這一通知的實現由 libsystemd-daemon.so 提供。
- Type=dbus:若以此方式啓動,當指定的 BusName 出如今DBus系統總線上時,systemd認爲服務就緒。
- Type=idle: systemd會等待全部任務(Jobs)處理完成後,纔開始執行idle類型的單元。除此以外,其餘行爲和Type=simple 相似。
type的更多解釋能夠參考 systemd.service(5)。
修改現存單元文件
要更改由軟件包提供的單元文件,先建立名爲 /etc/systemd/system/<單元名>.d/ 的目錄(如 /etc/systemd/system/httpd.service.d/),而後放入 *.conf 文件,其中能夠添加或重置參數。這裏設置的參數優先級高於原來的單元文件。例如,若是想添加一個額外的依賴,建立這麼一個文件便可:
- /etc/systemd/system/<unit>.d/customdependency.conf
- [Unit]
- Requires=<新依賴>
- After=<新依賴>
其它舉例,
- /etc/systemd/system/unit.d/customexec.conf
- [Service]
- ExecStartExecStart=
- ExecStart=new command
想知道爲何修改 ExecStart 前必須將其置空
下面是自動重啓服務的一個例子:
- /etc/systemd/system/unit.d/restart.conf
- [Service]
- Restart=always
- RestartSec=30
而後運行如下命令使更改生效:
- # systemctl daemon-reload
- # systemctl restart <單元>
此外,把舊的單元文件從 /usr/lib/systemd/system/ 複製到 /etc/systemd/system/,而後進行修改,也能夠達到一樣效果。在 /etc/systemd/system/ 目錄中的單元文件的優先級老是高於 /usr/lib/systemd/system/ 目錄中的同名單元文件。注意,當 /usr/lib/ 中的單元文件因軟件包升級變動時,/etc/ 中自定義的單元文件不會同步更新。此外,你還得執行 systemctl reenable <unit>,手動從新啓用該單元。所以,建議使用前面一種利用 *.conf 的方法。
小貼士: 用 systemd-delta 命令來查看哪些單元文件被覆蓋、哪些被修改。系統維護的時候須要及時瞭解哪些單元已經有了更新
單元配置文件的 vim 語法高亮支持
可從官方倉庫安裝 vim-systemd 軟件包,使 unit 配置文件在 Vim 下支持語法高亮。
目標(target)
啓 動級別(runlevel)是一箇舊的概念。如今,systemd 引入了一個和啓動級別功能類似又不一樣的概念——目標(target)。不像數字表示的啓動級別,每一個目標都有名字和獨特的功能,而且能同時啓用多個。一些 目標繼承其餘目標的服務,並啓動新服務。systemd 提供了一些模仿 sysvinit 啓動級別的目標,仍可使用舊的 telinit 啓動級別 命令切換。
獲取當前目標
不要使用 runlevel 命令了:
- $ systemctl list-units --type=target
建立新目標
在 Fedora 中,啓動級別 0、一、三、五、6 都被賦予特定用途,而且都對應一個 systemd 的目標。然而,沒有什麼很好的移植用戶定義的啓動級別(二、4)的方法。要實現相似功能,能夠以原有的啓動級別爲基礎,建立一個新的目標 /etc/systemd/system/<新目標>(能夠參考 /usr/lib/systemd/system/graphical.target),建立 /etc/systemd/system/<新目標>.wants 目錄,向其中加入額外服務的連接(指向 /usr/lib/systemd/system/ 中的單元文件)。
目標表
SysV 啓動級別 | 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) |
切換啓動級別/目標
systemd 中,啓動級別經過「目標單元」訪問。經過以下命令切換:
- # systemctl isolate graphical.target
該命令對下次啓動無影響。等價於telinit 3 或 telinit 5。
修改默認啓動級別/目標
開機啓動進的目標是 default.target,默認連接到 graphical.target (大體至關於原來的啓動級別5)。能夠經過內核參數更改默認啓動級別:
小貼士: 能夠省略擴展名 .target。
- systemd.unit=multi-user.target (大體至關於級別3)
- systemd.unit=rescue.target (大體至關於級別1)
另外一個方法是修改 default.target。能夠經過 systemctl 修改它:
- # systemctl enable multi-user.target
命令執行狀況由 systemctl 顯示:連接 /etc/systemd/system/default.target 被建立,指向新的默認啓動級別。該方法當且僅當目標配置文件中有如下內容時有效:
- [Install]
- Alias=default.target
目前,multi-user.target、graphical.target 都包含這段內容。
臨時文件
/usr/lib/tmpfiles.d/ 和 /etc/tmpfiles.d/ 中的文件描述了 systemd-tmpfiles 如何建立、清理、刪除臨時文件和目錄,這些文件和目錄一般存放在 /run 和 /tmp 中。配置文件名稱爲 /etc/tmpfiles.d/<program>.conf。此處的配置能覆蓋 /usr/lib/tmpfiles.d/ 目錄中的同名配置。
臨時文件一般和服務文件同時提供,以生成守護進程須要的文件和目錄。例如 Samba 服務須要目錄 /run/samba 存在並設置正確的權限位,就象這樣:
- /usr/lib/tmpfiles.d/samba.conf
- D /run/samba 0755 root root
此外,臨時文件還能夠用來在開機時向特定文件寫入某些內容。好比,要禁止系統從USB設備喚醒,利用舊的 /etc/rc.local 能夠用 echo USBE > /proc/acpi/wakeup,而如今能夠這麼作:
- /etc/tmpfiles.d/disable-usb-wake.conf
- w /proc/acpi/wakeup - - - - USBE
詳情參見 man 5 tmpfiles.d。
注意: 該方法不能向 /sys 中的配置文件添加參數,由於 systemd-tmpfiles-setup 有可能在相關模塊加載前運行。這種狀況下,須要首先經過 modinfo <模塊名> 確認須要的參數,並在 /etc/modprobe.d 下的一個文件中設置改參數。另外,還可使用 udev 規則,在設備就緒時設置相應屬性。
定時器
定時器是以 .timer 爲後綴的配置文件,記錄由system的裏面由時間觸發的動做, 定時器能夠替代 cron 的大部分功能。
日誌
systemd提供了本身日誌系統(logging system),稱爲 journal. 使用 systemd 日誌,無需額外安裝日誌服務(syslog)。讀取日誌的命令:
- # journalctl
默認狀況下(當 Storage= 在文件 /etc/systemd/journald.conf 中被設置爲 auto),日誌記錄將被寫入 /var/log/journal/。該目錄是 systemd 軟件包的一部分。若被刪除,systemd 不會自動建立它,直到下次升級軟件包時重建該目錄。若是該目錄缺失,systemd 會將日誌記錄寫入 /run/systemd/journal。這意味着,系統重啓後日志將丟失。
Tip: 若是 /var/log/journal/ 位於 btrfs 文件系統,應該考慮對這個目錄禁用寫入時複製
過濾輸出
journalctl能夠根據特定字段過濾輸出,例如:
顯示本次啓動後的全部日誌:
- # journalctl -b
不過,通常你們更關心的不是本次啓動後的日誌,而是上次啓動時的(例如,剛剛系統崩潰了)。可使用 -b 參數:
- journalctl -b -0 顯示本次啓動的信息
- journalctl -b -1 顯示上次啓動的信息
- journalctl -b -2 顯示上上次啓動的信息 journalctl -b -2
- Show all messages from date (and optional time):
- # journalctl --since="2012-10-30 18:17:16"
- Show all messages since 20 minutes ago:
- # journalctl --since "20 min ago"
- 顯示最新信息
- # journalctl -f
- 顯示特定程序的全部消息:
- # journalctl /usr/lib/systemd/systemd
- 顯示特定進程的全部消息:
- # journalctl _PID=1
- 顯示指定單元的全部消息:
- # journalctl -u netcfg
- Show kernel ring buffer:
- # journalctl -k
- Show auth.log equivalent by filtering on syslog facility:
- # journalctl -f -l SYSLOG_FACILITY=10
詳情參閱man journalctl、man systemd.journal-fields,以及Lennert的這篇博文
日誌大小限制
若是按上面的操做保留日誌的話,默認日誌最大限制爲所在文件系統容量的 10%,即:若是 /var/log/journal 儲存在 50GiB 的根分區中,那麼日誌最多存儲 5GiB 數據。能夠修改 /etc/systemd/journald.conf 中的 SystemMaxUse 來指定該最大限制。如限制日誌最大 50MiB:
- SystemMaxUse=50M
詳情參見 man journald.conf.
配合syslog使用
systemd提供了 socket /run/systemd/journal/syslog,以兼容傳統日誌服務。全部系統信息都會被傳入。要使傳統日誌服務工做,須要讓服務連接該 socket,而非 /dev/log(官方說明)。Arch 軟件倉庫中的 syslog-ng 已經包含了須要的配置。
設置開機啓動 syslog-ng:
- # systemctl enable syslog-ng
這裏有一份很不錯的 journalctl指南。
Forward journald to /dev/tty12
In /etc/systemd/journald.conf enable the following:
- ForwardToConsole=yes
- TTYPath=/dev/tty12
- MaxLevelConsole=info
重啓journald:
- # systemctl restart systemd-journald
疑難解答
關機/重啓十分緩慢
若是關機特別慢(甚至跟死機了同樣),極可能是某個拒不退出的服務在做怪。systemd 會等待一段時間,而後再嘗試殺死它。請閱讀這篇文章,確認你是不是該問題受害者。
短時進程無日誌記錄
若 journalctl -u foounit.service 沒有顯示某個短時進程的任何輸出,那麼改用 PID 試試。例如,若 systemd-modules-load.service 執行失敗,那麼先用 systemctl status systemd-modules-load 查詢其 PID(好比是123),而後檢索該 PID 相關的日誌 journalctl -b _PID=123。運行時進程的日誌元數據(諸如 _SYSTEMD_UNIT 和 _COMM)被亂序收集在 /proc 目錄。要修復該問題,必須修改內核,使其經過套接字鏈接來提供上述數據,該過程相似於 SCM_CREDENTIALS。
診斷啓動問題
使用以下內核參數引導: systemd.log_level=debug systemd.log_target=kmsg log_buf_len=1M
禁止在程序崩潰時轉儲內存
要使用老的內核轉儲,建立下面文件:
- /etc/sysctl.d/49-coredump.conf
- kernel.core_pattern = core
- kernel.core_uses_pid = 0
而後運行:
- # /usr/lib/systemd/systemd-sysctl
一樣可能須要執行"unlimit"設置文件大小:
- $ ulimit -c unlimited