[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

<<:  便利贴中的手势操作

>>:  System Design: 读书心得1

Day 15:专案02 - PTT C_Chat版爬虫02 | BeautifulSoup

大家安安,欢迎来到铁人赛的第15天! 不知不觉已经过完一半了,再努力坚持下去吧! 昨天已经将网站的原...

[DAY 01] 线上测验的难点与可能降低作弊的方法

因为疫情的关系,学校从5月中旬就开始了远(ㄕㄨˇ)距(ㄐㄧㄚˋ) 各级学校除了最开始的设备、网路问题...

找LeetCode上简单的题目来撑过30天啦(DAY10)

终於第十天了呀,我觉得要撑满30天好难,奇怪了我为甚麽要这麽勉强自己,压力爆棚压 题号:75 标题:...

[Day 17] Facial Recognition - siamese networks: 只是一个开始

双胞胎有同卵双生或异卵双生,孪生网路当然也要有 今天开始我们将谈谈如何让网路去学习辨识不同的人脸,...