Linux 初始化之 Systemd機制

來源:互聯網
上載者:User

標籤:dep   hostname   核心   topic   如何   lsb   內容   其它   hand   

systemd是Linux下的一種init軟體,由Lennart Poettering帶頭開發,其開發目標是提供更優秀的架構以表示系統服務間的依賴關係,並依此實現系統初始化時服務的並行啟動,同時達到降低Shell的系統開銷的效果,最終代替現在常用的System V與BSD風格init程式。傳統sysvinit使用inittab來決定運行哪些shell指令碼,大量使用shell指令碼被認為是效率低下無法並行的原因。systemd使用了Linux專屬技術,不再顧及POSIX相容.

設計理念

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

採用Socket啟用式與D-Bus啟用式服務,以提高相互依賴的各服務的並行運行效能;

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

從設計構思上說,由於systemd使用了cgroup與fanotify等組件以實現其特性,所以只適用於Linux。有鑒於此,考慮到kFreeBSD分支的軟體源無法納入systemd,為與其他分支保持一致,Debian開發人員儘力避免納入systemd。

應用範圍

systemd已納入眾多Linux發行版的軟體源中,以下簡表:

預設init程式為systemd的發行版

Fedora 15及後續版本

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_INET6、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

Log Service

systemd內建Log Service,參考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能夠Tracing Service的主進程。
  • 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

系統極客網站運行在 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」。

方法三: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 初始化之 Systemd機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.