systemctl用法及實例


前言

Systemd 是一系列工具的集合,其作用也遠遠不僅是啟動操作系統,它還接管了后台服務、結束、狀態查詢,以及日志歸檔、設備管理、電源管理、定時任務等許多職責,並支持通過特定事件(如插入特定 USB 設備)和特定端口數據觸發的 On-demand(按需)任務。

存放位置

系統服務,開機不需要登錄就能運行的程序(可以用於開機自啟)
/usr/lib/systemd/system
用戶服務,需要登錄后才能運行程序
/usr/lib/systemd/user
命名
一般xxx.service

Quick Start

nginx.service

[Unit]
Description=nginx
After=network.target 
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecStop=/usr/local/nginx/sbin/nginx -s stop -c /usr/local/nginx/conf/nginx.conf
ExecReload= /usr/local/nginx/sbin/nginx -s reload -c /usr/local/nginx/conf/nginx.conf
PrivateTmp=ture
[Install]
WantedBy=multi-user.target

code-server.service

[Unit]
Description=code-server background running.
After=network.target 

[Service]
Type=simple
Environment="PASSWORD=XXX"
EnvironmentFile=-/etc/code-server/code-server
PIDFile=/run/code-server.pid
ExecStart=/usr/bin/code-server --config /etc/code-server/code-server.config.yaml
KillSignal=control-group
ExecStop=/bin/kill -SIGTERM $MAINPID
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target

參數詳解

[Unit]

Description:簡短描述
Documentation:文檔地址
Requires:當前 Unit 依賴的其他 Unit,如果它們沒有運行,當前 Unit 會啟動失敗
Wants:與當前 Unit 配合的其他 Unit,如果它們沒有運行,當前 Unit 不會啟動失敗
BindsTo:與Requires類似,它指定的 Unit 如果退出,會導致當前 Unit 停止運行
Before:如果該字段指定的 Unit 也要啟動,那么必須在當前 Unit 之后啟動
After:如果該字段指定的 Unit 也要啟動,那么必須在當前 Unit 之前啟動
Conflicts:這里指定的 Unit 不能與當前 Unit 同時運行
Condition...:當前 Unit 運行必須滿足的條件,否則不會運行
Assert...:當前 Unit 運行必須滿足的條件,否則會報啟動失敗

    +-------------------+    +---------------------+
    |After->Condition...| -> |Requires -> Assert...| ->
    +-------------------+    +---------------------+
    +-----+    +-------+    +------+
 -> |Wants| -> |BindsTo| -> |Before| -> ...
    +-----+    +-------+    +------+

[Service]

Type:定義啟動時的進程行為。它有以下幾種值。
    Type=simple:(默認值)啟動一個子進程運行命令,用於不會退出的程序
    Type=forking:fork一個字進程,等待命令完成后退出,多用於后台進程 
    Type=oneshot:systemctl 等待命令完成再往下執行,像在控制台執行一個命令一樣
    Type=dbus:當前服務通過D-Bus啟動
    Type=notify:當前服務啟動完畢,會通知Systemd,再繼續往下執行
    Type=idle:若有其他任務執行完畢,當前服務才會運行
PIDFile:存放PID的絕對路徑
ExecStart:啟動當前服務的命令
ExecStartPre:啟動當前服務之前執行的命令
ExecStartPost:啟動當前服務之后執行的命令
ExecReload:重啟當前服務時執行的命令
ExecStop:停止當前服務時執行的命令
ExecStopPost:停止當其服務之后執行的命令
RestartSec:自動重啟當前服務間隔的秒數
Restart:定義何種情況 Systemd 會自動重啟當前服務 
    no(默認值): # 退出后無操作
    on-success:  # 只有正常退出時(退出狀態碼為0),才會重啟            
    on-failure:  # 非正常退出時,重啟,包括被信號終止和超時等
    on-abnormal: # 只有被信號終止或超時,才會重啟
    on-abort:    # 只有在收到沒有捕捉到的信號終止時,才會重啟
    on-watchdog: # 超時退出時,才會重啟
    always:      # 不管什么退出原因,都會重啟(除了systemctl stop)
    # 對於守護進程,推薦用on-failure
KillMode的類型:
    control-group(默認):# 當前控制組里的所有子進程,都會被殺掉
    process: # 只殺主進程
    mixed:   # 主進程將收到SIGTERM信號,子進程收到SIGKILL信號
    none:    # 沒有進程會被殺掉,只是執行服務的stop命令
PrivateTmp=true # 表示給服務分配獨立的臨時空間
TimeoutSec:停止命令執行前等待秒數。
TimeoutStartSec:啟動命令執行后等待秒數,超時停止。(0 關閉超時檢測)
TimeoutStopSec:停止命令執行后等待秒數,超時使用 SIGKILL 停止服務。
Environment:為服務指定環境變量。
EnvironmentFile:環境變量文件,一行一個不要有空格。
Nice:進程優先級(默認為0)其中 -20 為最高優先級,19 為最低優先級。
WorkingDirectory:指定服務的工作目錄,目錄不純在命令不能運行
RootDirectory:指定服務進程的根目錄(/ 目錄)。如果配置了這個參數,服務將無法訪問指定目錄以外的任何文件
User:指定運行服務的用戶
Group:指定運行服務的用戶組
MountFlags:服務的 Mount Namespace 配置,會影響進程上下文中掛載點的信息。
    shared:服務與主機共用一個 Mount Namespace,相互影響
    slave:服務使用獨立的 Mount Namespace,它會繼承主機掛載點,操作只有在自己的 Namespace 內生效。
    private:服務使用獨立的 Mount Namespace,它在啟動時沒有任何任何掛載點,服務對掛載點的操作也不會反映到主機上。
LimitCPU:LimitSTACK:\
LimitNOFILE:LimitNPROC: 限制特定服務的系統資源量,請看參考

    +-----------+    +----+
    |User->Group| -> |Nice| -> 
    +-----------+    +----+
    +---------------------------------+    +---------------+    +-------+
 -> |RootDirectory -> WorkingDirectory| -> |EnvironmentFile| -> |PIDFile|
    +---------------------------------+    +---------------+    +-------+
    +----+    +-------------------------------------------------------------+    
 -> |Type| -> |ExecStartPre -> ExecStart -> ExecStartPost -> TimeoutStartSec| -> 
    +----+    +-------------------------------------------------------------+ 
    +-------+    +------------------------+
 -> |Restart| -> |ExecReload -> RestartSec| -> 
    +-------+    +------------------------+
	+--------+    +--------------------------------------------------------+
 -> |KillMode| -> |TimeoutSec -> ExecStop -> ExecStopPost -> TimeoutStopSec| -> ...
    +--------+    +--------------------------------------------------------+

[Install]

WantedBy:Unit 激活時(enable)xxx.service符號鏈接會放入/etc/systemd/system/xxx.target.wants/目錄下面
    multi-user.target: # 表示多用戶命令行狀態,這個設置很重要
    graphical.target:  # 表示圖形用戶狀體,它依賴於multi-user.target
RequiredBy:Unit 激活時(enable)xxx.service符號鏈接會放入/etc/systemd/system/xxx.target.required/目錄下面
Alias:當前 Unit 可用於啟動的別名
Also:當前 Unit 激活(enable)時,會被同時激活的其他 Unit

Unit 文件占位符和模板

占位符

在 Unit 文件中,有時會需要使用到一些與運行環境有關的信息,例如節點 ID、運行服務的用戶等。這些信息可以使用占位符來表示,然后在實際運行被動態地替換實際的值。

%n:完整的 Unit 文件名字,包括 .service 后綴名
%p:Unit 模板文件名中 @ 符號之前的部分,不包括 @ 符號
%i:Unit 模板文件名中 @ 符號之后的部分,不包括 @ 符號和.service 后綴名
%t:存放系統運行文件的目錄,通常是 “run”
%u:運行服務的用戶,如果 Unit 文件中沒有指定,則默認為 root
%U:運行服務的用戶 ID
%h:運行服務的用戶 Home 目錄,即 %{HOME} 環境變量的值
%s:運行服務的用戶默認 Shell 類型,即 %{SHELL} 環境變量的值
%m:實際運行節點的 Machine ID,對於運行位置每個的服務比較有用
%b:Boot ID,這是一個隨機數,每個節點各不相同,並且每次節點重啟時都會改變
%H:實際運行節點的主機名
%v:內核版本,即 “uname -r” 命令輸出的內容
%%:在 Unit 模板文件中表示一個普通的百分號

模板

Unit 模板文件的寫法與普通的服務 Unit 文件基本相同,不過 Unit 模板的文件名是以 @ 符號結尾的。通過模板啟動服務實例時,需要在其文件名的 @ 字符后面附加一個參數字符串。

# apache@.service 模板
[Unit]
Description=My Advanced Service Template
After=etcd.service docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill apache%i
ExecStartPre=-/usr/bin/docker rm apache%i
ExecStartPre=/usr/bin/docker pull coreos/apache
ExecStart=/usr/bin/docker run --name apache%i -p %i:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStartPost=/usr/bin/etcdctl set /domains/example.com/%H:%i running
ExecStop=/usr/bin/docker stop apache1
ExecStopPost=/usr/bin/docker rm apache1
ExecStopPost=/usr/bin/etcdctl rm /domains/example.com/%H:%i
[Install]
WantedBy=multi-user.target

啟動服務

在服務啟動時需要在 @ 后面放置一個用於區分服務實例的附加字符參數,通常這個參數用於監控的端口號或控制台 TTY 編譯號。
Systemd 在運行服務時,總是會先嘗試找到一個完整匹配的 Unit 文件,如果沒有找到,才會嘗試選擇匹配模板。例如上面的命令,System 首先會在約定的目錄下尋找名為 apache@8080.service 的文件,如果沒有找到,而文件名中包含 @ 字符,它就會嘗試去掉后綴參數匹配模板文件。對於 apache@8080.service,systemd 會找到 apache@.service 模板文件,並通過這個模板文件將服務實例化。

systemctl start apache@8080.service

參考

# Systemd 服務管理教程

# Linux systemd資源控制初探


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM