iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0
Modern Web

網站一條龍 - 從架站到前端系列 第 12

[Day12] 讓 Linux 的 systemd 幫我們管理 API 程式

昨天我們成功的把 API 程式佈署到 GCP 的 VM 上了。不過,我們有一個問題:只要跑了 .NET 程式,這個 SSH 連線就被佔用了,如果要做其他事就得 ctrl+c 停止 API 程式。這種不方便的事我們當然不允許,今天我們就來把 API 程式包成 Linux service,讓 Linux 的 systemd 幫我們管理我們的程式。

建立 service unit 檔案

systemd 是現在主流 Linux 版本的服務管理程式,它能幫我們啟動、監控、停止與管理服務,甚至可以在程式掛掉的時候嘗試重啟服務。在把我們的程式託管給 systemd 之前,我們必須先建立代表我們 API 程式的 service unit
sudo touch /etc/systemd/system/ironman_api.service

再來,因為 service unit 會需要我們發佈完的檔案,所以先來手動發布一下我們的專案
cd /ironman/dotnet_api/IThomeIronman/ # 跳到 API 專案的資料夾
sudo dotnet publish -c Release # 執行 .NET CLI, 以 Release 模式發布方案

接著,用 vim 打開這個 service 檔案
sudo vi /etc/systemd/system/ironman_api.service
寫入 service unit 資訊

[Unit]
Description=IThome 2021 ironman API

[Service]
WorkingDirectory=/ironman/dotnet_api/IThomeIronman/Ithome_2021_API/bin/Release/net5.0/
ExecStart=/usr/bin/dotnet /ironman/dotnet_api/IThomeIronman/Ithome_2021_API/bin/Release/net5.0/Ithome_2021_API.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-ironman-api
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=ASPNETCORE_URLS=http://0.0.0.0:80;https://0.0.0.0:443
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

上面的設定檔各個參數解釋如下:

  • Description - 關於這個 service unit 的說明
  • WorkingDirectory - 程式運行時候的工作資料夾,程式中的相對路徑會以這個資料夾當參考點。通常我們會把這個資料夾指向 .NET buid/publish 出來的資料夾(~/bin/Release/net5.0/)
  • ExecStart - service unit 要執行的指令。請注意!這裡的 ExecStart 只有「一行」。前面的 /usr/bin/dotnet 是 .NET 命令工具的可執行檔位置,後面的路徑是發布(publish)完的 API 程式 dll 檔
  • Restart - 重啟條件。這邊我們設定一直嘗試重啟,若要設定成不重啟,可以設為 no
  • RestartSec - 重啟的間隔秒數
  • KillSignal - 設定收到什麼訊號時要殺掉這個 process,SIGINT 是中斷訊號,也就是 ctrl + c
  • SyslogIdentifier - 這個 service 在系統 log 中的識別名稱
  • User - 指定以哪個 Linux 上的使用者權限執行這個 service
  • Environment - 環境變數。這裡我們設定了三個環境變數:(1) 在 Production 模式下執行程式。(2) 指定監聽 80 port 的 http 連線與 443 port 的 https 連線。第三個環境變數我從以前到現在都還 google 不到一個自己覺得合理的解釋,就暫時跟著官網留著他(遮臉)
  • WantedBy - 指定這個 service 在哪幾個 RunLevel 需要被啟動。這個水有點深,筆者到現在仍是不太了解,一樣跟著官網範例(再遮臉)。有興趣的幫有可以參考這篇文章Wiki

執行 service

建好 service unit 檔案之後,就能用下面這個指令叫 systemd 幫我們啟動、管理我們的 API 程式。
sudo systemctl start ironman_api.service
systemctrl 是用來管理 service 的指令,start 代表啟動,後面的 ironman_api.service 是我們放在 /etc/systemd/system/ 資料夾底下建立的 service unit

啟動後,我們可以用 status 指令來檢查這個 service 的狀況,如果亮綠燈就代表成功跑起來了。
sudo systemctl status ironman_api.service
https://ithelp.ithome.com.tw/upload/images/20210912/20140664JDFSkvcWuT.png

啟動完 service,再一次到瀏覽器輸入 https://外部IP/api/User ,可以看到我們的 API 在正常發揮。

全部 OK 之後,我們要來設定「隨著系統啟動」,之前的Restart=always雖然會在程式掛掉的時候自動嘗試重啟,但是如果 VM 關機或重開機它就會停掉。雖然我們有設定WantedBy=multi-user.target,但我們還需要一個指令把我們的 service 加到自動啟動名單
sudo systemctl enable ironman_api.service

最後分享幾個常用的指令:

  • 停止 service - systemctl stop ironman_api.service
  • 重啟 service - systemctl restart ironman_api.service
  • 查看即時 log - journalctl -fu ironman_api.service 當程式有 bug 掛掉的時候,輸入這個指令就會看到噴錯然後重啟,然後再噴錯再重啟XD

上一篇
[Day11] 在 GCP 上建立 VM 與佈署 API 程式
下一篇
[Day13] 在 GCP 上面設定防火牆
系列文
網站一條龍 - 從架站到前端33

尚未有邦友留言

立即登入留言