Systemd簡介
Centos7 以上使用Systemd進行系統初始化,Systemd是Linux系統中最新的初始化工具,它可以有效的提高系統的啟動速度。
Systemd 默認從目錄/etc/systemd/system/讀取配置文件。然而,里面存放的大部分文件都是符號鏈接,它們指向目錄/usr/lib/systemd/system/,真正的配置文件(以 .service 結尾的文件)存放在那個目錄。
我們可以將自定義程序注冊為systemd service進程管理交給系統管理,可以方便啟動停止,也可以實現服務異常退出重啟,開機自啟動,減少自定義程序服務管理的時間消耗。
Systemd配置與命令
service文件參數詳解
service文件主要包含三個部分,分別是:[Unit]、[Service]、[Install]
如以下的nginx.service配置文件
# 配置文件內容
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
參數說明如下
| 參數名稱 | 參數說明 |
|---|---|
| [Unit] | |
| Description | 一段描述這個 Unit 文件的文字,通常只是簡短的一句話。 |
| Documentation | 指定服務的文檔,可以是一個或多個文檔的URL路徑。 |
| Requires | 依賴的其他 Unit 列表,列在其中的 Unit 模塊會在這個服務啟動的同時被啟動,並且如果其中有任意一個服務啟動失敗,這個服務也會被終止 |
| After | 與 Requires 相似,但會在后面列出的所有模塊全部啟動完成以后,才會啟動當前的服務。 |
| Before | 與 After 相反,在啟動指定的任一個模塊之前,都會首先確保當前服務已經運行。 |
| Wants | 與 Requires 相似,但只是在被配置的這個 Unit 啟動時,觸發啟動列出的每個 Unit 模塊,而不去考慮這些模塊啟動是否成功。 |
| Conflicts | 與這個模塊有沖突的模塊,如果列出模塊中有已經在運行的,這個服務就不能啟動,反之亦然。 |
| OnFailure | 當這個模塊啟動失敗時,就自動啟動列出的每個模塊。 |
| [Service] | |
| Type | 服務的類型,常用的有 simple(默認類型) 和 forking。默認的 simple 類型可以適應於絕大多數的場景,因此一般可以忽略這個參數的配置。而如果服務程序啟動后會通過 fork 系統調用創建子進程,然后關閉應用程序本身進程的情況,則應該將 Type 的值設置為 forking,否則 systemd 將不會跟蹤子進程的行為,而認為服務已經退出。 |
| Environment | 為服務添加環境變量 |
| EnvironmentFile | 指定加載一個包含服務所需的環境變量列表的文件,文件中的每一行都是一個環境變量的定義。 |
| ExecStart | 這個參數是幾乎每個 .service 文件都會有的,指定服務啟動的主要命令,在每個配置文件中只能使用一次。(需要使用絕對路徑) |
| ExecStartPre | 指定在啟動執行 ExecStart 的命令前的准備工作,可以有多個,所有命令會按照文件中書寫的順序依次被執行。 |
| ExecStartPost | 指定在啟動執行 ExecStart 的命令后的收尾工作,也可以有多個。 |
| ExecStop | 停止服務所需要執行的主要命令。(需要使用絕對路徑) |
| ExecStopPost | 指定在 ExecStop 命令執行后的收尾工作,也可以有多個。 |
| ExecReload | 重新加載服務所需執行的主要命令。(需要使用絕對路徑) |
| Restart | 這個值用於指定在什么情況下需要重啟服務進程。常用的值有 no,on-success,on-failure,on-abnormal,on-abort 和 always。默認值為 no,即不會自動重啟服務。這些不同的值分別表示了在哪些情況下,服務會被重新啟動 |
| RestartSec | 如果服務需要被重啟,這個參數的值為服務被重啟前的等待秒數。 |
| Nice | 服務的進程優先級,值越小優先級越高,默認為0。-20為最高優先級,19為最低優先級。 |
| WorkingDirectory | 指定服務的工作目錄。 |
| RootDirectory | 指定服務進程的根目錄( / 目錄),如果配置了這個參數后,服務將無法訪問指定目錄以外的任何文件。 |
| User | 指定運行服務的用戶,會影響服務對本地文件系統的訪問權限。 |
| Group | 指定運行服務的用戶組,會影響服務對本地文件系統的訪問權限。 |
| PrivateTmp | 是否給服務分配獨立的臨時空間(true/false) |
| [Install] | |
| WantedBy | 和前面的 Wants 作用相似,只是后面列出的不是服務所依賴的模塊,而是依賴當前服務的模塊。“WantedBy=multi-user.target” 表明當系統以多用戶方式(默認的運行級別)啟動時,這個服務需要被自動運行。當然還需要 systemctl enable 激活這個服務以后自動運行才會生效。 |
| RequiredBy | 和前面的 Requires 作用相似,同樣后面列出的不是服務所依賴的模塊,而是依賴當前服務的模塊。 |
| Also | 當這個服務被 enable/disable 時,將自動 enable/disable 后面列出的每個模塊。 |
注意:[Service]的啟動、重啟、停止命令全部要求使用絕對路徑
想了解更詳細的參數說明可以在systemd.service 中文手冊中查看
systemctl常用命令
以nginx.service為例
# 啟動nginx服務
systemctl start nginx.service
# 停止nginx服務
systemctl stop nginx.service
# 重啟nginx服務
systemctl restart nginx.service
# 查看nginx服務狀態
systemctl status nginx.service
# 在開機時啟用一個服務
systemctl enable nginx.service
# 在開機時禁用一個服務
systemctl disable nginx.service
# 查看服務是否開機啟動
systemctl is-enabled nginx.service
# 重新讀取nginx配置(不用停止nginx服務就能使修改的配置生效)
systemctl reload nginx.service
# 重新加載systemd(一般修改完配置文件執行該命令使配置生效)
systemctl daemon-reload
# 查看已啟動的服務列表
systemctl list-unit-files | grep enabled
# 查看啟動失敗的服務列表
systemctl --failed
其中,systemctl enable命令用於/etc/systemd/system/和/usr/lib/systemd/system/兩個目錄之間,建立符號鏈接關系。
systemctl enable nginx.service
# 等同於
ln -s '/usr/lib/systemd/system/nginx.service' '/etc/systemd/system/multi-user.target.wants/nginx.service'
systemd 默認從目錄/etc/systemd/system/讀取配置文件,所以systemctl enable命令相當於激活開機啟動。
同理,systemctl disable用於撤銷兩個目錄之間的符號鏈接關系,也就撤銷了開機啟動。
編寫systemd自啟動服務
在上面內容的基礎下,我們嘗試編寫一個自己的systemd服務,本次的systemd服務主要是執行一段python腳本。
在/root/pyfile路徑(這里可以改為你自己的路徑)下創建run.py,內容如下
import time
import string
import random
f = open('/root/pyfile/a.txt', 'w')
for i in range(100):
words = ''.join(random.sample(string.ascii_lowercase, 5))
row = '--- No.{}, {} ---\n'.format(i, words)
f.write(row)
f.flush()
time.sleep(2)
f.close()
以上腳本的作用是在100次遍歷中,每2s生成一個隨機的單詞,並將單詞寫入到a.txt中。
接下來我們來編寫自定義的systemd服務,在/usr/lib/systemd/system路徑下新建pyscript.service服務,內容如下
[Unit]
Description=python script
[Service]
Type=simple
WorkingDirectory=/root/pyfile
ExecStart=python run.py
[Install]
WantedBy=multi-user.target
編寫完成后,保存並執行以下命令
systemctl daemon-reload
systemctl start pyscript.service
進入/root/pyfile目錄下執行tail -f a.txt可以看出每2s打印一個隨機單詞,如下
--- No.0, jkqdr ---
--- No.1, beqvu ---
--- No.2, eaqrw ---
--- No.3, kuljf ---
--- No.4, qmzhl ---
接下來我們設置開機啟動pyscript.service服務
systemctl start pyscript.service
執行后系統生成了一個符號鏈接,如下
Created symlink /etc/systemd/system/multi-user.target.wants/pyscript.service → /usr/lib/systemd/system/pyscript.service.
然后重啟服務器,等待重啟完畢后,執行以下命令查看python腳本是否執行
ps -ef | grep python
可以發現多了如下進程
root 738 1 0 18:00 ? 00:00:00 /usr/bin/python run.py
再次進入/root/pyfile目錄,執行tail -f a.txt,可以發現文本正在打印。
自此,我們已經成功完成了自定義systemd服務的編寫和啟動。
