Linux 初始化之 Systemd機制

systemd是Linux下的一種init軟件,由Lennart Poettering帶頭開發,其開發目標是提供更優秀的框架以表示系統服務間的依賴關係,並依此實現系統初始化時服務的並行啓動,同時達到下降Shell的系統開銷的效果,最終代替如今經常使用的System V與BSD風格init程序。傳統sysvinit使用inittab來決定運行哪些shell腳本,大量使用shell腳本被認爲是效率低下沒法並行的緣由。systemd使用了Linux專屬技術,再也不顧及POSIX兼容.php

設計理念前端

與多數發行版使用的System V風格init相比,systemd採用瞭如下新技術:linux

採用Socket激活式與D-Bus激活式服務,以提升相互依賴的各服務的並行運行性能;shell

用cgroups代替PID來追蹤進程,以此即便是兩次fork以後生成的守護進程也不會脫離systemd的控制。服務器

從設計構思上說,因爲systemd使用了cgroup與fanotify等組件以實現其特性,因此只適用於Linux。有鑑於此,考慮到kFreeBSD分支的軟件源沒法歸入systemd,爲與其餘分支保持一致,Debian開發者盡力避免歸入systemd。網絡

應用範圍session

systemd已歸入衆多Linux發行版的軟件源中,如下簡表:框架

默認init程序爲systemd的發行版less

Fedora 15及後續版本ssh

Mageia 2[10]

Mandriva 2011[11]

openSUSE 12.1及後續版本[12]

Arch Linux在2012年10月13日將systemd-sysvcompat歸入base軟件組,自此Arch Linux默認安裝完即以systemd爲init程序[13],同時也提供了與Arch自帶啓動腳本兼容用的systemd啓動腳本包以方便用戶,使用戶能「開箱即用」[14]

Chakra GNU/Linux,在2012.10的光盤鏡像文件發佈後默認使用systemd。[15]

可使用systemd的發行版

Debian GNU/Linux,於「testing」分支源中提供[16],並在2014年的技術委員會的init系統投票中決定在Debian 8 「Jessie」中將以Linux爲核心的版本轉換到systemd[17] 。

Gentoo,同Openrc一塊兒被Gentoo官方支持[18][19][20]

除此之外,systemd已由Lennart Poettering提請歸入GNOME 3.2的外部依賴關係列表[21],而這意味着全部使用GNOME的發行版都應該使用systemd,最低限度來講也必須將其做爲配置選項之一。

一些其餘的發行版也把它包含進來,做爲 upstart 和 sysvinit 的替代品。

 

systemd 特色

systemd 開啓和監督整個系統是基於 unit 的概念。unit 是由一個與配置文件對應的名字和類型組成的(例如:avahi.service unit 有一個具備相同名字的配置文件,是守護進程 Avahi 的一個封裝單元)unit 有如下幾種類型:

service :守護進程的啓動、中止、重啓和重載是此類 unit 中最爲明顯的幾個類型。

socket :此類 unit 封裝系統和互聯網中的一個 socket 。當下,systemd 支持流式、數據報和連續包的 AF_INET、AF_INET六、AF_UNIX socket 。也支持傳統的 FIFOs 傳輸模式。每個 socket unit 都有一個相應的服務 unit 。相應的服務在第一個「鏈接」進入 socket 或 FIFO 時就會啓動(例如:nscd.socket 在有新鏈接後便啓動 nscd.service)。

device :此類 unit 封裝一個存在於 Linux 設備樹中的設備。每個使用 udev 規則標記的設備都將會在 systemd 中做爲一個設備 unit 出現。udev 的屬性設置能夠做爲配置設備 unit 依賴關係的配置源。

mount :此類 unit 封裝系統結構層次中的一個掛載點。

automount :此類 unit 封裝系統結構層次中的一個自掛載點。每個自掛載 unit 對應一個已掛載的掛載 unit (須要在自掛載目錄能夠存取的狀況下儘早掛載)。

target :此類 unit 爲其餘 unit 進行邏輯分組。它們自己實際上並不作什麼,只是引用其餘 unit 而已。這樣即可以對 unit 作一個統一的控制。(例如:multi-user.target 至關於在傳統使用 SysV 的系統中運行級別5);bluetooth.target 只有在藍牙適配器可用的狀況下才調用與藍牙相關的服務,如:bluetooth 守護進程、obex 守護進程等)

snapshot :與 target unit 類似,快照自己不作什麼,惟一的目的就是引用其餘 unit 。

systemd 的工具

  • systemctl :用做內省和控制 systemd 系統和服務管理器的狀態。
  • systemd-cgls:以樹形遞歸顯示選中的 Linux 控制組結構層次。
  • systemadm:一個 systemd 系統和服務管理器的圖形化前端。是 systemd-gtk 軟件包的一部分。這還只是前期版本,尚需完善。除非你是一個開發者,不然請不要使用它。

 

systemd 包含了本身的配置和診斷工具,在使用它處理系統啓動問題時用到的技巧不一樣於 sysvinit。因爲它與 upstart 和 sysvinit 的兼容特性,咱們在使用這兩個初始化工具的發行版裏面熟悉的命令與技巧也適用於 systemd。

 systemctl 命令

檢視和控制systemd的主要命令是systemctl。該命令可用於查看系統狀態和管理系統及服務。詳見man 1 systemctl。該工具在改變配置文件或從新啓動後臺程序時須要 root 權限,但即便是非 root 用戶也能下達一些診斷的命令。若是你在啓動該命令時不加任何參數,你會看到一個系統啓動時執行任務的「單位(unit)」列表,包括掛載及檢測磁盤、啓動後臺服務及配置硬件。

1)輸出激活的單元

$ systemctl

如下命令等效:

$ systemctl list-units

輸出運行失敗的單元:

$ systemctl --failed

全部可用的單元文件存放在 /usr/lib/systemd/system/  /etc/systemd/system/ 目錄(後者優先級更高)。查看全部已安裝服務:

$ systemctl list-unit-files

2)使用單元

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

使用 systemctl 控制單元時,一般須要使用單元文件的全名,包括擴展名(例如 sshd.service)。可是有些單元能夠在systemctl中使用簡寫方式。

  • 若是無擴展名,systemctl 默認把擴展名看成 .service。例如 netcfg 和 netcfg.service 是等價的。
  • 掛載點會自動轉化爲相應的 .mount 單元。例如 /home 等價於 home.mount。
  • 設備會自動轉化爲相應的 .device 單元,因此 /dev/sda2 等價於 dev-sda2.device。

當即激活單元:

# 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

3服務

服務(service)單位是最重要的一類單位之一,由於它們管理着後臺服務,而在使用 sysvinit 的發行版裏面則通常使用初始化腳原本啓動這些服務。掛載(mount)與自動掛載(automount)單位用來掛載文件系統。

套接字(socket)單位用來建立套接字,並在訪問套接字後,當即利用依賴關係間接地啓動另外一單位。你可使用參數讓 systemctl 只列出某個類型的單位,如全部的服務單位:systemctl --type=service

systemd 自動將其輸出結果遞交給 less 顯示;你不只可使用箭頭鍵來上下滾動,也能夠向右滾動,由於有時更多的信息會偶爾「藏」到那裏。

列表中的第一欄是單位的名字,

第二欄則表示該單位的定義是否已由 systemd 正確加載。

第三欄則告訴咱們該單位是否正在運行。若是你使用了 -a 參數,那麼該程序將僅顯示非正在運行的單位,即已安裝但並未在啓動時使用的單位,同時也包含引導系統未能正常加載的單位文件(緣由極可能爲該單位文件出現錯誤)。

第四欄則給出了當前狀態:「exited」表示該進程已經無任何錯誤地完成,這種狀況適用於一諸如進程在啓動後並不在後臺繼續運行的狀況,例如,在系統啓動時因爲考慮到兼容性因素執行在 sysvinit 裏面經常使用的 /etc/rc.d/rc.local 文件的服務單位。「Running」表示正在後臺運行的服務,如 cron、dbus、sshd 和 udev。

第五欄是對該單位的描述。標有「LSB」或「SYSV」的單位已由 systemd 自動建立以管理傳統啓動腳本。

不能啓動或啓動後崩潰的服務在第四欄中用紅色標爲「failed」(若是終端能夠顯示彩色)。你能夠以下命令來察看該服務是什麼時候崩潰的以及在服務程序結束後提供了什麼錯誤代碼:

systemctl status ntpd.service

對於一個新安裝的 Linux Deepin 12.06,systemctl 會列出約50個服務型單位,包含文本終端的登錄進程(agetty)。由於 systemd 不一樣於 sysvinit, 它會像管理普通的後臺服務同樣以服務單位的形式對這些進程進行管理。

 

4)單位文件與目標(target)

 

一單位的處理

建立單位用的系統配置文件位於 /lib/systemd/system/,但 /etc/systemd/system 目錄下的同名文件會優先於前者。

單位文件的定義一般比傳統的 sysvinit 腳本要短得多。例如,用於經過 NTP 來同步網絡時間的服務只有短短几行:

[Unit]

Description=Network Time Service

 

[Service]

ExecStart=/usr/bin/ntpd -n -u ntp:ntp -g

 

[Install]

WantedBy=multi-user.target

1)      全部的單位文件都包含由[Unit]開頭的一節,其中包含通常設置與簡

2)      [Service]一節含有針對該服務要進行的任務的指定設置——對於 NTP 來講,僅須要啓動該服務的命令行。若是須要用一個指定的命令來終止程序,你能夠用 ExecStop= 來進行設置。這一步對於 NTP 守護進程是不須要的,由於根據 Unix 傳統,它能夠用一個簡單的「SIGTERM」信號來結束。若是沒有指定其餘命令,這個命令會告訴 systemd 結束任務。

3)      [Install]一節包含了 systemd 在(反)安裝時要解釋的說明;這裏的 NTP 一例中,其內容意爲在「多用戶」目標激活時應當同步時間。

二目標

「目標」單位的概念與 sysvinit 的運行級別類似;實際上,爲考慮兼容性,systemd 甚至可以識別與目標對應的運行級別名稱。因此,你能夠在引導裝載程序中的 kernel 一行中加入 single 這個參數;systemd 就會激活 rescue.target,提供一個至關於單用戶模式的最小化界面。

在 systemd 中,多用戶模式(即不使用圖形化登錄界面就徹底啓動系統的模式)由 multi-user.target 表示,能夠經過下面這個連接來將其設爲默認啓動目標:

ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target

若是此後你確實須要默認啓動圖形化登錄界面,可用一樣的方式來將 graphical.target 設爲默認目標。這等同於傳統初始化工具的運行級別 5。你也能夠在引導裝載程序中爲 kernel 指定想要啓動的目標單位:

systemd.unit=multi-user.target

 

 若是想要在操做過程當中激活一個不一樣的目標單位,你可使用 systemctl 的isolate 命令(須要 root 權限):

systemctl isolate rescue.target

切換爲 rescue 目標對於管理任務來講頗有用,systemd 這時會中止全部的用戶登錄與後臺服務,只有系統服務在運行,如監視邏輯卷的服務(lvm2-monitor)。有時,甚至這些服務也須要中止並從新安裝,這時你可使用 emergency.target 來進入緊急模式(emergency mode),這時只有命令提示符的進程以及內核線程在運行。

 

 systemctl命令取代了rc.d命令

開機模塊加載

/etc/modules-load.d/.conf,至關於原rc.conf中的MODULES變量

# Load virtio-net.ko at boot virtio-net

virtio-net

模塊黑名單仍在/etc/modprobe.d/下,如blacklist.conf:

blacklist badmod.ko

Locale

/etc/locale.conf,至關於原rc.conf中的LOCALE

LANG=en_US.UTF-8 LC_COLLATE=C

LC_COLLATE=C

日誌服務

systemd自帶日誌服務,參考systemd Journal

sudo journalctl

能夠刪除syslog-ng了

主機名

/etc/hostname,至關於原來rc.conf中的HOSTNAME變量

myhostname

網絡

sudo systemctl enable NetworkManager.service

不象rc.conf有專門的配置簡單網絡的地方,仍是用NetworkManager、wicd之類的工具吧

若是你堅持使用簡單靜態配置,能夠參考[SOLVED] static ethernet setup under systemd?

運行級別

systemdtarget替代了runlevel的概念,提供了更大的靈活性,如你能夠繼承一個已有的target,並添加其它服務,來建立本身的target

sudo systemctl list-units --type=target #查詢當前target

sudo systemctl isolate graphical.target #改變當前target,重啓無效

sudo systemctl enable multi-user.target #改變啓動時默認target

sudo systemctl enable kdm.service #graphical是默認target,指定使用的display manager

優化

systemd有本身的」e4rat」

sudo systemctl enable systemd-readahead-collect.service sudo systemctl enable systemd-readahead-replay.service

/etc/fstab,修改/home分區options,檢查/home分區時並行啓動其它服務

defaults,noauto,x-systemd.automount

其餘

sudo systemctl reboot #systemctl還有系統關機、重啓、掛起等功能 sudo systemctl suspend

 

 

本身編寫 .service 文件

systemd 的單元文件是受 XDG Desktop Entry .desktop 文件啓發而產生,而最初起源是 Windows 下的 .ini 文件。

示例參見:Systemd/Services

處理依賴關係

使用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= 參數進行設置。具體的參數說明請參閱 man systemd.service 。

  • 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認爲服務就緒。

修改現存單元文件

要更改由軟件包提供的單元文件,先建立名爲 /etc/systemd/system/<單元名>.d/ 的目錄(如 /etc/systemd/system/httpd.service.d/),而後放入 *.conf 文件,其中能夠添加或重置參數。這裏設置的參數優先級高於原來的單元文件。例如,若是想添加一個額外的依賴,建立這麼一個文件便可:

/etc/systemd/system/<unit>.d/customdependency.conf

[Unit]

Requires=<新依賴>

After=<新依賴>

而後運行如下命令使更改生效:

# 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 命令來查看哪些單元文件被覆蓋、哪些被修改。

 

eg:slock

Locks the system with the help of slock. Very handy when closing the laptop lid for example.

/etc/systemd/system/screenlock.service

[Unit]

Description=Lock X session using slock

Before=sleep.target

 

[Service]

User=<username>

Environment=DISPLAY=:0

ExecStart=/usr/bin/slock

 

[Install]

WantedBy=sleep.target

 

如何定製或增長一個自定義 unit 文件?

unit 文件在 /etc/systemd/system 下的優先級要高於 /lib/systemd/system 下的。按照我的的需求從後者移動到前者並進行自定義修改。

若是一行以 .include 開始,後接文件名,那麼該文件在此時被解析爲特殊文件。請確保包含的文件在指令前有適當的章節頭信息。

若是可能的話,你應當使用 .include 聲明 unit 文件而不是在 /lib/systemd/system 下複製整個 unit 文件到 /etc/systemd/system 目錄下。這樣你才能夠在未來升級軟件包時正確地升級未改變的指令。

在使用 .include 和指令時須要當心,由於它能夠有屢次定義(像 EnvironmentFile= 同樣)。因爲咱們只能添加新指令而不能刪除已定義的指令,此時,咱們就必須從 /lib/systemd/system複製整個文件到 /etc/systemd/system 中去。

假設咱們有一個 lighttpd 服務,咱們如今想下降它的 niceness 值。咱們須要作的就只是添加 Nice=-5 到 lighttpd.service 文件中。咱們能夠經過複製整個文件/lib/systemd/system/lighttpd.service 到 /etc/systemd/system/lighttpd.service 或者在 /etc/systemd/system/lighttpd.service 中建立以下文件作到

.include /lib/systemd/system/lighttpd.service

[Service]

Nice=-5

不要忘記在編輯一個 unit 文件後使用 systemdctl daemon-reload 重載 systemd 守護進程。

檢測到 Linux 所使用的虛擬化平臺類型。

方法一:dmidecode

要檢測 Linux 底層的虛擬化類型首選的就是 dmidecode 命令,它最初設計來顯示系統 BIOS 和硬件組件的相關信息。使用以下命令即可以檢測相關虛擬化信息:

sudo dmidecode -s system-manufacturer

檢測Linux虛擬化平臺類型的幾種方式

系統極客網站運行在 Microsoft Azure 平臺上,因此檢測出來是微軟的 Hyper-V。若是你的系統運行在物理服務器上,輸入的將是硬件製造商的實際名稱(如 Dell Inc.)。若是你的 Linux 是運行在虛擬化平臺中,則會顯示所使用的虛擬化技術相關名稱,如 「Microsoft Corporation」「QEMU」「Xen」「VirtualBox」「VMware, Inc」等等。

注意:該方法不適用於基於容器的虛擬化技術。

方法二:systemd

對於使用 systemd 的 Linux 系統,可使用 systemd-detect-virt 命令來進行檢測,該命令目前能夠同時檢測到基於 hypervisor 的虛擬化技術(例如 KVM、QEMU、VMware、Xen、Oracle VM、VirtualBox、UML)和基於容器的虛擬化技術(例如 LXC、Docker、OpenVZ)。

systemd-detect-virt

注意:在物理服務器上使用該命令會輸出「none」。

檢測Linux虛擬化平臺類型的幾種方式

方法三:virt-what

咱們介紹的最後一種檢測 Linux 所使用虛擬化類型的方法是 virt-what 命令,virt-what 其實是一個 Shell 腳本。它經過各類啓發式方法來識別虛擬化環境類型,能夠檢測出 QEMU/KVM、VMware、Hyper-V、VirtualBox、OpenVZ/Virtuozzo、Xen、LXC、IBM PowerVM 以及 Parallels 等平臺類型。

在使用以前,你們須要先經過 apt-get 或 yum 安裝 virt-what,再執行以下命令進行檢測:

sudo virt-what

檢測Linux虛擬化平臺類型的幾種方式

相關文章
相關標籤/搜索