layout: post
title: Linux之systemd服務配置及自動重啟
date: 2019-09-09
tags: linux
Linux之systemd服務配置及自動重啟
0 背景
在linux上開發時,往往需要將自己的程序做成服務,並且實現服務開機自動重啟,以及服務崩潰后自動重啟功能,本文就對該功能的實現做簡單介紹,實現方法很簡單,使用linux系統的systemd即可實現
1 systemd介紹
歷史上,linux的啟動一直采用init進程,比如
$ sudo /etc/init.d/apache2 start
或者
$ service apache2 start
這種方法有兩個缺點。
一是啟動時間長。init進程是串行啟動,只有前一個進程啟動完,才會啟動下一個進程。
二是啟動腳本復雜。init進程只是執行啟動腳本,不管其他事情。腳本需要自己處理各種情況,這往往使得腳本變得很長。
Systemd 就是為了解決這些問題而誕生的。它的設計目標是,為系統的啟動和管理提供一套完整的解決方案。
根據 Linux 慣例,字母d是守護進程(daemon)的縮寫。 Systemd 這個名字的含義,就是它要守護整個系統。使用了 Systemd,就不需要再用init了。Systemd 取代了initd,成為系統的第一個進程(PID 等於 1),其他進程都是它的子進程。
systemctl是 Systemd 的主命令,用於管理系統。對於用戶來說,最常用的是下面這些命令,用於啟動和停止 Unit(主要是 service)。
-立即啟動一個服務
$ systemctl start apache.service
-立即停止一個服務
$ systemctl stop apache.service
-重啟一個服務
$ systemctl restart apache.service
-殺死一個服務的所有子進程
$ systemctl kill apache.service
-重新加載一個服務的配置文件
$ systemctl reload apache.service
-重載所有修改過的配置文件
$ systemctl daemon-reload
-顯示某個 Unit 的所有底層參數
$ systemctl show httpd.service
-顯示某個 Unit 的指定屬性的值
$ systemctl show -p CPUShares httpd.service
-設置某個 Unit 的指定屬性
$ systemctl set-property httpd.service CPUShares=500
本文主要是對systemd的使用進行介紹,如果想進一步了解systemd的基本知識,可查閱相關資料
2 服務端腳本
這里我們寫一個php的服務腳本server.php,用來實現一個服務
<?php
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock, '0.0.0.0', 10000);
for (;;) {
socket_recvfrom($sock, $message, 1024, 0, $ip, $port);
$reply = str_rot13($message);
socket_sendto($sock, $reply, strlen($reply), 0, $ip, $port);
}
運行后可使用lsof指令來查看端口占用情況
lthpc@lthpc:~$ lsof -i:10000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
php 40446 lthpc 3u IPv4 37381218 0t0 UDP *:10000
使用nc指令模擬客戶端測試
$ nc -u 127.0.0.1 10000
Hello, world!
Uryyb, jbeyq!
3 創建服務
接下來使用systemd創建一個服務,寫一個服務配置文件/etc/systemd/system/rot13.service
[Unit]
Description=ROT13 demo service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=ltpc
ExecStart=/usr/bin/env php /path/to/server.php
[Install]
WantedBy=multi-user.target
有幾點需要注意,為了使服務能夠自動無限次重啟,需要增加以下幾個配置
StartLimitIntervalSec=0
Restart=always
RestartSec=1
關於配置文件的具體參數含義,可參考該文檔
設置好后,可以運行如下語句啟動服務
$ systemctl start rot13
運行后,便啟動了名為rot13的服務,可使用status查看服務狀態
lthpc@lthpc:~/workspace_zong/tcptest$ systemctl status rot13
● rot13.service - ROT13 demo service
Loaded: loaded (/etc/systemd/system/rot13.service; disabled; vendor preset: enabled)
Active: active (running) since 一 2019-10-28 11:25:43 CST; 1min 28s ago
Main PID: 44532 (php)
Tasks: 1
Memory: 5.2M
CPU: 24ms
CGroup: /system.slice/rot13.service
└─44532 php /home/lthpc/workspace_zong/tcptest/server.php
10月 28 11:25:43 lthpc systemd[1]: Started ROT13 demo service.
為了開機自動啟動,執行下以下語句
$ systemctl enable rot13
同樣的,可以使用nc指令模擬客戶端測試,可以看到服務已經正常啟動運行了!
4 自動重啟
為了測試是否可以正常自動重啟,我們手動殺掉啟動的服務進程,再查看進程號發現已經更換PID號了,說明重啟過進程,並且使用nc -u 127.0.0.1 10000指令測試依然可以調用服務
$ systemctl status rot13 | grep PID
Main PID: 44532 (php)
$ sudo kill 44532
$ systemctl status rot13 | grep PID
Main PID: 44255 (php)
注意輸入systemctl stop rot13
時服務是不會重啟的,所以如果有參數需要修改,直接運行stop指令改完再start就可以了
編寫服務配置
vim /lib/systemd/system/website.service
[Unit]
Description=website
After=network.target
[Service]
Type=forking
ExecStart=/home/monitor/website/start.sh
ExecReload=/home/monitor/website/restart.sh
ExecStop=/home/monitor/website/shutdown.sh
[Install]
WantedBy=multi-user.target
編寫對應啟動停止等腳本
開啟:
vim /home/monitor/website/start.sh
#!/bin/sh
export JAVA_HOME=/usr/java/jdk1.8.0_144
export PATH=$JAVA_HOME/bin:$PATH
nohup java -jar /home/monitor/website/demo-0.0.1-SNAPSHOT.jar &
關閉:
vim /home/monitor/website/shutdown.sh
#!/bin/sh
ps -ef | grep demo-0.0.1-SNAPSHOT.jar | grep -v grep | awk '{print $2}' | xargs kill -9
重啟:
vim /home/monitor/website/restart.sh
#!/bin/sh
export JAVA_HOME=/usr/java/jdk1.8.0_144
export PATH=$JAVA_HOME/bin:$PATH
ps -ef | grep demo-0.0.1-SNAPSHOT.jar | grep -v grep | awk '{print $2}' | xargs kill -9
nohup java -jar /home/monitor/website/demo-0.0.1-SNAPSHOT.jar &
授權運行:
chmod +x start.sh shutdown.sh restart.sh
配置自啟動
開機啟動:systemctl enable website
啟動:systemctl start website
關閉:systemctl stop website
重啟:systemctl restart website
查看狀態:systemctl status website
修改服務配置重新生效:systemctl daemon-reload
常見systemctl錯誤碼
code | desc |
---|---|
0 | 命令成功結束 |
1 | 通用未知錯誤 |
2 | 誤用shell命令 |
126 | 命令不可執行 |
127 | 沒找到命令 |
128 | 無效退出參數 |
128+x | Linux 信號x的嚴重錯誤 |
130 | Linux 信號2 的嚴重錯誤,即命令通過SIGINT(Ctrl+C)終止 |
203 | 缺失腳本執行器標識 |
255 | 退出狀態碼越界 |
備注
如運行sh腳本報出如下錯誤:
/bin/sh^M: 壞的解釋器: 沒有那個文件或目錄
是由於在windows下編輯的腳本文件拷貝至linux導致的,windows下編輯文本每一行結尾是\n\r,而Linux下則是\n,
解決方法:
在終端輸入sed -i 's/\r$//' daemon.sh
sed -i 's/\r$//' daemon.sh 會把make-all-linux-project.sh中的行尾的\r替換為空白,其中daemon.sh為報錯的腳本。
為避免該錯誤,可以直接在linux新建腳本或者再linux環境下拷貝。