本篇介紹如何在 Linux 系統中自行建立一個網路伺服器,並設定讓 Systemd 自動啟動與管理伺服器的運作。
首先以 Python 撰寫一個簡單的 echo 伺服器,將其儲存在 /opt/echo_server.py
:
#!/usr/bin/env python3 import socket # 建立 socket serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 綁定所有網路介面的 9000 連接埠 serv.bind(('0.0.0.0', 9000)) # 開始接受 client 連線 serv.listen() while True: # 接受 client 連線 conn, addr = serv.accept() print('Client from', addr) while True: # 接收資料 data = conn.recv(1024) # 若無資料則離開 if not data: break # 傳送資料 conn.send(data) conn.close() print('Client disconnected')
這段 Python 程式碼在執行之後,會傾聽所有網路介面的 9000
連接埠,建立連線之後將所有收到的資料送回 client 端。
建立好 /opt/echo_server.py
之後,順便開啟執行權限:
# 開啟執行權限 chmod +x /opt/echo_server.py
我們可以先手動測試一下,啟動 echo 伺服器:
# 啟動 echo 伺服器(server 端)
/opt/echo_server.py
接著開啟另外一個終端機,使用 nc
指令連線至 9000
連接埠
# 連線至 localhost 的 9000 連接埠(client 端) nc localhost 9000
連上之後,隨意輸入一些文字,送出之後應該就會看到伺服器回應相同的文字,而在伺服器端應該也會顯示一些關於 client 的資訊,這樣就代表 echo 伺服器可以正常運作了。
建立一個新的 Systemd 服務單位設定檔,儲存於 /etc/systemd/system/echo_server.service
:
[Unit] Description=Echo Server [Service] Type=simple ExecStart=/opt/echo_server.py Restart=always [Install] WantedBy=multi-user.target
權限要設定為 644
:
sudo chmod 644 /etc/systemd/system/echo_server.service
如果在開發過程中,有修改過 Systemd 的服務單位設定檔,記得重新載入 daemon 讓新設定生效:
# 重新載入 Systemd 設定檔
sudo systemctl daemon-reload
接著就可以使用 systemctl
指令啟動自訂的 echo 伺服器:
# 啟動自訂的 echo 伺服器
sudo systemctl start echo_server
查看 echo 伺服器的狀態:
# 查看 echo 伺服器狀態
systemctl status echo_server
● echo_server.service - Echo Server Loaded: loaded (/etc/systemd/system/echo_server.service; disabled; vendor pre Active: active (running) since Thu 2019-09-19 06:59:46 UTC; 1min 46s ago Main PID: 20142 (python3) Tasks: 1 (limit: 4915) CGroup: /system.slice/echo_server.service └─20142 python3 /opt/echo_server.py Sep 19 06:59:46 test-vm systemd[1]: Started Echo Server.
這樣就成功啟動了自己開發的 echo 伺服器了,此時我們可以直接使用上面的 nc
指令測試一下伺服器是否正常運作。
如果要停止 echo 伺服器,可執行:
# 停止 echo 伺服器
sudo systemctl stop echo_server
如果想要讓 echo 伺服器可以在開機時自動啟動,可執行:
# 設定開機自動啟動 echo 伺服器
sudo systemctl enable echo_server
Created symlink /etc/systemd/system/multi-user.target.wants/echo_server.service → /etc/systemd/system/echo_server.service.
若要取消開機自動啟動 echo 伺服器,則可執行:
# 取消開機自動啟動 echo 伺服器
sudo systemctl disable echo_server
Removed /etc/systemd/system/multi-user.target.wants/echo_server.service.
關於 systemctl
指令的詳細用法,請參考 Linux systemd 系統服務管理基礎教學文章。
Systemd 服務單位設定檔的完整文件可以從線上手冊查詢:
# 查詢 Systemd 服務單位設定檔說明文件
man systemd.unit
man systemd.service
man systemd.exec
另外亦可從 /lib/systemd/system/
(Ubuntu)或 /usr/lib/systemd/system/
(CentOS)目錄中找到大量的實際範例。
以下是一個比較詳細的 Systemd 服務單位設定檔範本,在撰寫自訂服務的設定檔時,可以先複製這份設定再接著修改:
[Unit] # 服務名稱 Description=Your Server # 服務相關文件 # Documentation=https://example.com # Documentation=man:nginx(8) # 設定服務啟動的先後相依姓,例如在網路啟動之後: # After=network.target [Service] # 行程類型 Type=simple # 啟動服務指令 ExecStart=/opt/your_command # 服務行程 PID(通常配合 forking 的服務使用) # PIDFile=/run/your_server.pid # 啟動服務前,執行的指令 # ExecStartPre=/opt/your_command # 啟動服務後,執行的指令 # ExecStartPost=/opt/your_command # 停止服務指令 # ExecStop=/opt/your_command # 停止服務後,執行的指令 # ExecStopPost=/opt/your_command # 重新載入服務指令 # ExecReload=/opt/your_command # 服務終止時自動重新啟動 Restart=always # 重新啟動時間格時間(預設為 100ms) # RestartSec=3s # 啟動服務逾時秒數 # TimeoutStartSec=3s # 停止服務逾時秒數 # TimeoutStopSec=3s # 執行時的工作目錄 # WorkingDirectory=/opt/your_folder # 執行服務的使用者(名稱或 ID 皆可) # User=myuser # 執行服務的群組(名稱或 ID 皆可) # User=mygroup # 環境變數設定 # Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" # 服務輸出訊息導向設定 # StandardOutput=syslog # 服務錯誤訊息導向設定 # StandardError=syslog # 設定服務在 Syslog 中的名稱 # SyslogIdentifier=your-server [Install] WantedBy=multi-user.target
參考資料:PubNub、Benjamin Morel、Linode、LinuxConfig.org、TecAdmin.net