Linux之systemd服務配置及自動重啓


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環境下拷貝。

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