systemd及啓動流程

CentOS 7 使用systemd替換了SysV。Systemd目的是要取代Unix時代以來一直在使用的init系統,兼容SysV和LSB的啓動腳本,而且夠在進程啓動過程中更有效地引導加載服務。

systemd的特性有:

  • 支持並行化任務

  • 同時採用socket式與D-Bus總線式激活服務;

  • 按需啓動守護進程(daemon);

  • 利用 Linux 的 cgroups 監視進程;

  • 支持快照和系統恢復;

  • 維護掛載點和自動掛載點;

  • 各服務間基於依賴關係進行精密控制。

systemd基本工具

輸出激活的單元:

  1. $ systemctl

以下命令等效:

  1. $ systemctl list-units

輸出運行失敗的單元:

  1. $ systemctl --failed

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

  1. $ systemctl list-unit-files

使用單元

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

使用 systemctl 控制單元時,通常需要使用單元文件的全名,包括擴展名(例如 sshd.service)。但是有些單元可以在systemctl中使用簡寫方式。

  • 如果無擴展名,systemctl 默認把擴展名當作 .service。例如 netcfg 和 netcfg.service 是等價的。

  • 掛載點會自動轉化爲相應的 .mount 單元。例如 /home 等價於 home.mount。

  • 設備會自動轉化爲相應的 .device 單元,所以 /dev/sda2 等價於 dev-sda2.device。

注: 有一些單元的名稱包含一個 @ 標記, (e.g. [email protected]): 這意味着它是模板單元 [email protected] 的一個 實例。 string 被稱作實例標識符, 在 systemctl 調用模板單元時,會將其當作一個參數傳給模板單元,模板單元會使用這個傳入的參數代替模板中的 %I 指示符。 在實例化之前,systemd 會先檢查 [email protected] 文件是否存在(如果存在,應該就是直接使用這個文件,而不是模板實例化了)。大多數情況下,包換 @ 標記都意味着這個文件是模板。如果一個模板單元沒有實例化就調用,該調用會返回失敗,因爲模板單元中的 %I 指示符沒有被替換。

立即激活單元:

  1. # systemctl start <單元>

立即停止單元:

  1. # systemctl stop <單元>

重啓單元:

  1. # systemctl restart <單元>

命令單元重新讀取配置:

  1. # systemctl reload <單元>

輸出單元運行狀態:

  1. $ systemctl status <單元>

檢查單元是否配置爲自動啓動:

  1. $ systemctl is-enabled <單元>

開機自動激活單元:

  1. # systemctl enable <單元>

注意: 如果服務沒有Install段落,一般意味着應該通過其它服務自動調用它們。如果真的需要手動安裝,可以直接連接服務,如下(將foo替換爲真實的服務名):

  1. # ln -s /usr/lib/systemd/system/foo.service /etc/systemd/system/graphical.target.wants/

取消開機自動激活單元:

  1. # systemctl disable <單元>

顯示單元的手冊頁(必須由單元文件提供):

  1. # systemctl help <單元>

重新載入 systemd,掃描新的或有變動的單元:

  1. # systemctl daemon-reload

電源管理

安裝 polkit 後纔可使用電源管理。

如果你正登錄在一個本地的systemd-logind用戶會話,且當前沒有其它活動的會話,那麼以下命令無需root權限即可執行。否則(例如,當前有另一個用戶登錄在某個tty),systemd 將會自動請求輸入root密碼。

重啓:

  1. $ systemctl reboot

退出系統並停止電源:

  1. $ systemctl poweroff

待機:

  1. $ systemctl suspend

休眠:

  1. $ systemctl hibernate

混合休眠模式(同時休眠到硬盤並待機):

  1. $ 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 文件,其中可以添加或重置參數。這裏設置的參數優先級高於原來的單元文件。例如,如果想添加一個額外的依賴,創建這麼一個文件即可:

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

  2. [Unit]

  3. Requires=<新依賴>

  4. After=<新依賴>

其它舉例,

  1. /etc/systemd/system/unit.d/customexec.conf


  2. [Service]

  3. ExecStartExecStart=

  4. ExecStart=new command

想知道爲什麼修改 ExecStart 前必須將其置空

下面是自動重啓服務的一個例子:

  1. /etc/systemd/system/unit.d/restart.conf


  2. [Service]

  3. Restart=always

  4. RestartSec=30

然後運行以下命令使更改生效:

  1. # systemctl daemon-reload

  2. # 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 命令了:

  1. $ systemctl list-units --type=target

創建新目標

在 Fedora 中,啓動級別 0、1、3、5、6 都被賦予特定用途,並且都對應一個 systemd 的目標。然而,沒有什麼很好的移植用戶定義的啓動級別(2、4)的方法。要實現類似功能,可以以原有的啓動級別爲基礎,創建一個新的目標 /etc/systemd/system/<新目標>(可以參考 /usr/lib/systemd/system/graphical.target),創建 /etc/systemd/system/<新目標>.wants 目錄,向其中加入額外服務的鏈接(指向 /usr/lib/systemd/system/ 中的單元文件)。

目標表

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

切換啓動級別/目標

systemd 中,啓動級別通過“目標單元”訪問。通過如下命令切換:

  1. # 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 修改它:

  1. # systemctl enable multi-user.target

命令執行情況由 systemctl 顯示:鏈接 /etc/systemd/system/default.target 被創建,指向新的默認啓動級別。該方法當且僅當目標配置文件中有以下內容時有效:

  1. [Install]

  2. 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 存在並設置正確的權限位,就象這樣:

  1. /usr/lib/tmpfiles.d/samba.conf

  2. D /run/samba 0755 root root

此外,臨時文件還可以用來在開機時向特定文件寫入某些內容。比如,要禁止系統從USB設備喚醒,利用舊的 /etc/rc.local 可以用 echo USBE > /proc/acpi/wakeup,而現在可以這麼做:

  1. /etc/tmpfiles.d/disable-usb-wake.conf

  2. 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)。讀取日誌的命令:

  1. # journalctl

默認情況下(當 Storage= 在文件 /etc/systemd/journald.conf 中被設置爲 auto),日誌記錄將被寫入 /var/log/journal/。該目錄是 systemd 軟件包的一部分。若被刪除,systemd 不會自動創建它,直到下次升級軟件包時重建該目錄。如果該目錄缺失,systemd 會將日誌記錄寫入 /run/systemd/journal。這意味着,系統重啓後日志將丟失。

Tip: 如果 /var/log/journal/ 位於 btrfs 文件系統,應該考慮對這個目錄禁用寫入時複製

過濾輸出

journalctl可以根據特定字段過濾輸出,例如:

顯示本次啓動後的所有日誌:

  1. # journalctl -b

不過,一般大家更關心的不是本次啓動後的日誌,而是上次啓動時的(例如,剛剛系統崩潰了)。可以使用 -b 參數:

  • journalctl -b -0 顯示本次啓動的信息

  • journalctl -b -1 顯示上次啓動的信息

  • journalctl -b -2 顯示上上次啓動的信息 journalctl -b -2

  • Show all messages from date (and optional time):

  1. # journalctl --since="2012-10-30 18:17:16"

  • Show all messages since 20 minutes ago:

  1. # journalctl --since "20 min ago"

  • 顯示最新信息

  1. # journalctl -f

  • 顯示特定程序的所有消息:

  1. # journalctl /usr/lib/systemd/systemd

  • 顯示特定進程的所有消息:

  1. # journalctl _PID=1

  • 顯示指定單元的所有消息:

  1. # journalctl -u netcfg

  • Show kernel ring buffer:

  1. # journalctl -k

  • Show auth.log equivalent by filtering on syslog facility:

  1. # 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:

  1. SystemMaxUse=50M

詳情參見 man journald.conf.

配合syslog使用

systemd提供了 socket /run/systemd/journal/syslog,以兼容傳統日誌服務。所有系統信息都會被傳入。要使傳統日誌服務工作,需要讓服務鏈接該 socket,而非 /dev/log(官方說明)。Arch 軟件倉庫中的 syslog-ng 已經包含了需要的配置。

設置開機啓動 syslog-ng:

  1. # systemctl enable syslog-ng

這裏有一份很不錯的 journalctl指南。

Forward journald to /dev/tty12

In /etc/systemd/journald.conf enable the following:

  1. ForwardToConsole=yes

  2. TTYPath=/dev/tty12

  3. MaxLevelConsole=info

重啓journald:

  1. # systemctl restart systemd-journald

centos5啓動流程

 1.加電自檢 POST (Power-on self testing)

  主板上的ROM中存儲的BIOS程序,被主板芯片映射入內存,從而協助CPU工作

 2.根據BIOS啓動順序依次訪問各個存儲設備,檢查其MBR中是否有引導程序,如果有,則將引導程序加載至內存,並且將硬件的管理權移交給引導程序

 3.引導程序(GRUB),開始加載stage1_5,以驅動文件系統,然後從根設備加載stage2至內存;stage2的代碼會從同一磁盤分區加載kernel至內存,同時將硬件的管理權移交給kernel

 4.kernel試圖掛載根文件系統,如果其內部有被直接編譯進內核的文件系統驅動程序,則無需其他輔助直接以只讀的方式掛載根文件系統即可,否則,必須依賴於ramdisk提供的臨時根文件系統作爲過渡,待文件系統驅動成功以後,完成根切換的工作,以只讀方式掛在真正的根文件系統

 5.kernel試圖啓動第一個進程:/sbin/init,而後kernel轉入後臺,將用戶空間的進程管理任務交給init進程來完成

 6.init程序讀取其配置文件:/etc/inittab

 7.設置系統當前的運行級別

 8.執行/etc/rc.d/rc.sysinit腳本,實施系統初始化

 9.執行/etc/rc.d/rc腳本,並且處理/etc/rc.d/rc$runlevel.d下面的所有服務的連接,所有以K開頭的服務都被停止,所有以S開頭的服務都被啓動;

 10.根據運行級別選擇打開的終端數量及位置;

 11.使用mingetty命令調用login命令,爲用戶打印登錄提示符;

Bootloader:

    GRUB:

      grub 0.x:grub legacy

      grub 1.x:grub2


    grub

      1st stage:MBR

      1_5 stage:MBR之後的若干扇區中;

      2nd stage:磁盤的啓動分區;


      stage2:

        提供啓動菜單

        命令行接口

        交互式界面

        提供配置文件

        加密保護菜單及內核

        ...

          (hd#,#)


          root (hd0,0)

          kernel /vmlinuz-VERSION-release ro root=UUID="DEVICE_UUID" selinux=0 /sbin/init

          initrd /initrd-VERSION-release


      grub的配置文件

        /boot/grub/grub.conf <--- /etc/grub.conf

          default=0

          timeout=5

          hiddenmenu

          splashp_w_picpath=(hd0,0)/*.xpm.gz

          password --md5 CRYPTED_PASSWORD

          title OS_ID

            root (hd0,0)

            kernel /vmlinuz-VERSION-release ARGUMENTS...

            initrd /initrd-VERSION-release

systmd的新特性

  1.在系統引導的時候可以實現服務的並行啓動

  2.能夠實現按需激活進程

   在系統啓動時,需要隨系統啓動服務,其服務進程並沒有啓動,


Systemd:

  Systemd的新特性:

    1.在系統引導的時候可以實現服務的並行啓動;

    2.能夠實現按需激活進程;

      在系統啓動時,需要隨系統啓動服務,其服務進程並沒有啓動,但是Systemd爲每一個此類服務進程都註冊了對應的套接字;我們成這種服務處理方式爲"半激活狀態";

    3.能夠對當前系統的用戶空間的每個進程進行狀態快照;以後如果進程出現問題或故障,可以迅速恢復進程狀態至過去的某一時刻;

    4.systemd內部有一種基於依賴關係來定義的服務控制邏輯;


  核心管理概念:unit文件 

    由systemd相關的配置文件進行標識、識別和配置功能的實現的基礎;

    unit的文件分類:

      系統服務類

      socket

      目標類

      快照類

      ...


    這些配置文件主要保存在:

      /usr/lib/systemd/system/*

      /etc/systemd/system/*   符號鏈接

      /run/systemd/system/*   非配置關鍵項;


    Unit文件的常見類型:

      Service unit:文件的擴展名爲.service,用於定義系統服務,一般.service擴展名可以省略;


      Target unit:文件的擴展名爲.target,用於模擬實現"init程序的運行級別";


      Device unit:文件的擴展名爲.device,用於定義內核識別出來的各設備;


      Mount unit:文件的擴展名爲.mount,用於定義可以被systemd管理的文件系統的掛載點;


      Automount unit:文件的擴展名爲.automount,用於定義文件系統的自動掛載點的位置;


      Socket unit:文件的擴展名爲.socket,用於標識進程間通信所用到的socket文件;


      Swap unit:文件的擴展名爲.swap,用於標識swap設備;


      Path unit:文件的擴展名爲.path,用於監控指定目錄中的一個文件或一個子目錄;如果被監控的文件或目錄不存在,則systemd可以自動創建之;


  systemd特性的實現方式:

    1.基於socket unit的方式實現進程激活機制;

    2.基於device unit的方式實現設備的自動識別,掛載;

    3.基於bus的激活機制:

    4.基於path的激活機制;


  systemd的兼容和不兼容:

    兼容:SysV init的腳本;

    不兼容:必須使用systemctl命令來管理系統,systemctl命令的格式是固定不變的;所有不經由systemd啓動的系統服務或系統功能,systemctl命令無法與之直接通信,也就意味着此類服務或功能,無法通過systemctl來控制;


  systemctl命令:

    systemctl - Control the systemd system and service manager


    systemctl [OPTIONS...] COMMAND [NAME...]


    管理服務類的操作:

      啓動:service NAME start ==> systemctl start NAME[.service]

      停止:service NAME stop ==> systemctl stop NAME.service

      重啓:service NAME restart ==> systemctl restart NAME.service

      狀態:service NAME status ==> systemctl status NAME.service

      設置服務的開機自啓:chkconfig --level runlevels NAME on ==> systemctl enable NAME.service

      禁止服務的開機自啓:chkconfig --level runlevels NAME off ==> systemctl disable NAME.service

      查看某服務是否開機自啓:chkconfig --list NAME ==> systemctl is-enabled NAME.service

      條件式重啓:service NAME condrestart ==> systemctl try-restart NAME.service

      重載配置文件:service NAME reload ==> systemctl reload NAME.service


      重載或重啓:systemctl reload-or-restart NAME.service

      重載或條件式重啓:systemctl reload-or-try-restart NAME.service


      查看某服務當前是否處於激活狀態:systemctl is-active NAME.service

      查看所有已處於激活狀態的服務:systemctl list-units 

        --type=UNIT_TYPE:查看指定unit類型的處於活躍狀態的服務;

        --all:顯示所有,包括處於活躍狀態和處於非活躍狀態的各服務;

      查看依賴指定服務的其他服務:systemctl list-dependencies NAME.service


      禁止某服務被設定爲開機自啓:systemctl mask NAME.service

      取消禁止某服務被設定爲開機自啓:systemctl unmask NAME.service


    管理target unit:

      模擬運行級別:

        0 ==> runlevel0.target, poweroff.target

        1 ==> runlevel1.target, rescue.target

        2 ==> runlevel2.target, multi-user.target

        3 ==> runlevel3.target, multi-user.target

        4 ==> runlevel4.target, multi-user.target

        5 ==> runlevel5.target, graphical.target

        6 ==> runlevel6.target, shutdown.target


      運行級別間切換:init # ==> systemctl isolate NAME.target

        注意:不是所有的target都能使用上述命令進行級別切換的;只有那些在對應的unit文件中包含了AllowIsolate=yes的語法的target才能用於切換;


        修改了unit文件之後,需要通過命令才能使之生效;

        # systemctl daemon-reload 


      查看運行級別:runlevel ==> systemctl list-units --type=target --all


      查看默認運行級別:/etc/inittab(id:3:initdefault:) ==> systemctl get-default 

      修改默認運行級別:/etc/inittab(id:3:initdefault:) ==> systemctl set-default NAME.target


      rescue.target:緊急救援模式

        systemctl isolate rescue.target

        systemctl rescue


      emergency.target:緊急調試模式

        systemctl emergency


      rescue模式,相當於安全模式,在切換到此模式時,操作系統會運行最底層的驅動程序,以保證服務器可以運行起來;


      emergency模式,一般來說,通常是硬件故障,或者硬件不可識別,或者硬件可識別但不可用等關乎於計算機硬件設施的問題,通常系統會啓動emergency模式;


    除上述模式之外,傳統的init命令,shutdown命令,poweroff命令,halt命令,reboot命令其實都是systemctl的符號鏈接;


    可以使用systemctl命令來直接實現上述功能:

      關機:systemctl halt,systemctl poweroff

      重啓:systemctl reboot

      掛起:systemctl suspend

      休眠(進程快照):systemctl hibernate

      掛起並休眠:systemctl hybrid-sleep


  Service unit file的基本文件格式:

    /etc/systemd/system:存放的都是各個unit file的符號鏈接;

    /usr/lib/systemd/system


    如果自行編寫unit file,可以直接將文件放置於/etc/systemd/system目錄中;也可以將其放在/usr/lib/systemd/system目錄中,但是需要爲其提供一個符號鏈接文件放置於/etc/systemd/system目錄中;


    Service unit file文件的基本格式:

      此類unit file通常分爲三段:

        [Unit]:定義與Unit類型無關的通用選項;用於提供當前unit的描述信息,unit的行爲信息,unit的依賴關係,unit相關幫助文檔信息等;

          常用的選項語句:

            Description:定義相關服務的描述信息;意義性的介紹性的描述;

            After:定義了此服務在啓動前必須依賴的其他服務;

            Before:定義了依賴此服務啓動的其他服務;

            Wants:指明依賴關係,說明該服務依賴於哪些其他的unit;弱依賴,即使被依賴的服務並沒有被正確激活,也不會影響當前服務是否可以被激活;

            Requires:指明依賴關係,說明該服務依賴於哪些其他的unit;強依賴,只要被依賴的unit無法被正確激活,則當前服務一定無法激活;

            Conflict:定義了各unit之間可能存在衝突;

            Documentation:定義了跟當前unit相關的管理命令的文檔所在;


        [Service]:定義與系統服務相關的專用的選項語句;

          常用的選項語句:

            Type:用於定義影響ExecStart即相關參數的功能的unit進程的啓動類型;

              simple:默認值,表示由ExecStart語句指明的應用程序啓動的進程就是主進程;

              forking:複製自身,表示有ExecStart語句指明的應用程序所啓動的進程中衆多的子進程中一個將成爲主進程,而一旦啓動完成,父進程會退出;

              oneshot:一次性進程,功能類似與simple,在啓動後續的unit之前,主進程會退出;

              notify:功能類似於simple,但是其後續的unit僅在通過sd_notify()函數發送通知之後,才能運行ExecStart所指明的應用程序;

            EnvironmentFile:環境配置文件,此文件一般用於在ExecStart之前被讀取,併爲ExecStart執行後面的應用程序提供必要的變量以及其他自定義功能等;

            ExecStart:指明啓動此服務所需要運行的命令或腳本;

            ExecReload:指明重載配置文件所需要運行的命令或腳本;

            ExecStop:指明停止服務所需要運行的命令或腳本;

            ExecStartPre:指明在執行ExecStart指明的命令之前需要運行的命令或腳本;

            ExecStartPost:指明在執行ExecStart指明的命令之後需要運行的命令或腳本;

            Restart:表示如果服務遭遇有意外而終止,則會自動重啓該服務;


        [Install]:定義由"systemctl enable"和"systemctl disable"命令在實現服務啓動或禁用時用到的專用選項語句;

          WantedBy:弱依賴關係,指的是該服務被哪些其他units所依賴;

          RequiredBy:強依賴關係,指的是該服務被哪些其他units所依賴;


CentOS 7系統引導過程:

  1.POST

  2.選擇啓動設備,讀取引導程序

  3.裝載引導程序(CentOS 7使用的grub2)

  4.裝載引導程序的配置文件: /etc/grub.d/, /etc/default/grub , /boot/grub2/grub.cfg

  5.加載initramfs驅動模塊

  6.加載內核

  7.內核以只讀方式掛載rootfs,啓動systemd進程;

  8.執行initrd-*.target所有的unit,包括掛載/etc/fstab文件中所有有效的文件系統;

  9.根切換

  10.systemd執行默認的target


Linux Kernel:

  內核設計流派:

    單內核設計,但是充分借鑑了微內核體系設計的優點,爲內核引入了模塊化機制,內核高度模塊化;

    內核被模塊化之後,一些最爲基本最爲重要的內容,被編譯到內核核心;而其他更多的功能則以模塊的方式來提供;而且支持動態裝載和卸載各內核模塊;


  內核的組成部分:

    kernel:內核核心文件,一般爲bzImage,經過壓縮處理的鏡像文件;通常內核核心文件保存在/boot目錄下,名稱爲vmlinuz-VERSION-release


    kernel object(ko):內核對象,內核額外功能模塊,一般該類文件放置於/lib/modules/VERSION-release


      注意:內核模塊與內核核心,版本號必須嚴格匹配;


      內核模塊其實就是內核源代碼的一部分,只是在編譯內核的過程中,由於其功能可能並非內核核心所必需,所以以模塊的方式被編譯;


      在編譯內核時,內核的功能通常有如下幾種選擇方式:

        [ ] kernel Function:No,不選擇編譯此功能;

        [M] kernel Function:Modules,將此功能編譯爲內核模塊使用;此功能不佔據內核空間,只佔用磁盤空間;

        [*] kernel Function:Yes,將此功能直接編譯進內核核心;


    ramdisk:內核補充文件,輔助文件,對於內核核心來說,此文件非必須,是否使用此文件取決於內核能否直接驅動rootfs所在的存儲設備;

      設備的驅動程序,SCSI設備的驅動;

      邏輯設備驅動程序:LVM的驅動程序,軟RAID驅動程序等;

      文件系統:


      cpio -i -F initramfs-2.6.32-573.el6.x86_64.img


      簡化的rootfs


    注意:一般來講,kernel核心文件和ramdisk文件必須具有完全相同的版本號;


內核管理的相關命令:

  uname命令:

    uname - print system information

    uname [OPTION]...

      常用選項:

        -n:顯示節點名稱

        -r:顯示內核版本號,包括VERSION和release

        -a:顯示所有信息


  lsmod命令:

    lsmod - program to show the status of modules in the Linux Kernel


    顯示有Linux內核核心已經裝載的內核模塊;


    lsmod顯示的內容,分爲三個字段:

      模塊名稱  模塊大小  被引用次數及被誰所引用


  modinfo命令:

    modinfo - program to show information about a Linux Kernel module


    modinfo  [ -k kernel ]  [ modulename|filename... ]

      常用選項:

        -F field:僅顯示指定字段的信息;通常只能指定一個字段;

        -n:只顯示模塊文件的絕對路徑   (最常用)

        -a:只顯示模塊的作者信息

        -d:只顯示模塊的描述

        -l:只顯示許可證信息

        -p:只顯示模塊參數信息


  depmod命令:

    depmod - program to generate modules.dep and map files


    內核模塊依賴關係文件及系統信息映射文件的生成工具


  實現內核模塊的動態裝載和卸載的命令:

    insmod命令:裝載指定的內核模塊文件,但無法自動解決模塊間的依賴關係;

      insmod - simple program to insert a module into the Linux Kernel


      insmod [ filename ]  [ module options... ]


      注意:filename:模塊文件的絕對路徑;


      ]# insmod `modinfo -n btrfs`


    rmmod命令:

      rmmod - simple program to remove a module from the Linux Kernel


      # rmmod module_name


    modprobe命令:

      modprobe - program to add and remove modules from the Linux Kernel

      從內核中移除模塊或者向內核中插入模塊;


      modprobe  [ -C config-file ] [ modulename ]  [ module parameters... ]


        默認的配置文件:/etc/modprobe.conf , /etc/modprobe.d/*


        modprobe module_name:裝載模塊,自動識別和解決依賴關係;


        modprobe -r module_name:卸載模塊


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章