.NET Worker Service 部署到 Linux 作为 Systemd Service 运行

系统 Linux
在本文中,我通过一个实例详细介绍了如何将 .NET Worker Service 部署到 Linux 系统作为 Systemd Service 运行,并说明了如何使用 systemctl 命令来管理服务,如何使用 journalctl 命令查看 Systemd 服务日志。

[[407943]]

本文转载自微信公众号「技术译站」,作者技术译站。转载本文请联系技术译站公众号。

今天我接着介绍一下如何将 Worker Service 部署到 Linux 上,并作为 Systemd Service 运行。

我在本文中要覆盖的内容包含:

  • 作为 Linux 控制台程序运行
  • 作为 Systemd Service 运行
  • 开机自动启动、查看日志信息

创建项目并发布

§下载 Worker Service 源码

我将基于上一篇文章中的 Worker Service 源码来修改,如果您安装有 git,可以用下面的命令获取它:

  1. git clone git@github.com:ITTranslate/WorkerServiceAsWindowsService.git 

然后,使用 Visual Studio Code 打开此项目,构建一下,以确保一切正常:

  1. dotnet build 

§删除用不到的依赖项

删除上一篇文章中用于 Windows Services 的依赖程序包:

  1. git clone git@github.com:ITTranslate/WorkerServiceAsWindowsService.git 

然后,删除 Program.cs 中的 .UseWindowsService() 方法调用。

§修改配置文件

打开配置文件 appsettings.json,将日志文件保存路径中的 \ 改为 /,其他不用做任何更改。

  1.   "Name""RollingFile"
  2.   "Args": { 
  3.     "pathFormat""Logs/{Hour}.log"
  4.     "outputTemplate""{Timestamp:o} [{Level:u3}] ({MachineName}/{ProcessId}/{ProcessName}/{ThreadId}) {Message}{NewLine}{Exception}" 
  5.   } 
  6. }, 
  7.   "Name""SQLite"
  8.   "Args": { 
  9.     "sqliteDbPath""Logs/log.db"
  10.     "tableName""Logs"
  11.     "maxDatabaseSize": 1, 
  12.     "rollOver"true 
  13.   } 

这是因为 Windows 中使用反斜杠 \ 来表示目录,而 Linux 中使用正斜杠 / 来表示目录。

假如不修改保存路径,您将会看到日志被保存成如下的尴尬文件名:

  1. 'Logs\2021061715.log' 
  2. 'Logs\log.db' 

§发布程序

运行 dotnet publish 命令将应用程序及其依赖项发布到文件夹。

  1. dotnet publish -c Release -r linux-x64 -o c:\test\workerpub\linux 

这里我使用 -r linux-x64 参数,指定发布独立部署于 Linux 系统的应用程序。

命令运行完成后,您会在 C:\test\workerpub\linux 文件夹中看到适用于 Linux 系统的可执行程序及其所有依赖项。

作为 Linux 控制台程序运行

将文件夹 C:\test\workerpub\linux 下的文件压缩为 linux.zip。

打开 Xshell 工具,连接到一台 Linux 测试机(我的测试机操作系统为 CentOS 7.3),在测试机上新建 /srv/Worker 目录:

  1. mkdir /srv/Worker 

使用 rz 命令将 linux.zip 复制到测试机,

然后在测试机上解压 linux.zip 到 /srv/Worker 目录:

  1. unzip linux.zip -d /srv/Worker 

为我们的应用程序分配可执行权限,并运行:

  1. # 分配可执行权限 
  2. chmod +x /srv/Worker/MyService 
  3. # 运行 
  4. /srv/Worker/MyService 

按下 Ctrl+C 关闭应用,等待关闭前必须完成的任务正常结束后,应用退出。输入 ls /srv/Worker 命令回车,您会看到在该目录下多了一个 Logs 目录,日志文件输出正常。

作为 Systemd Service 运行

§添加 Systemd Service 依赖

为了让我们的 Worker 监听来自 Systemd 的启动和停止信号,我们需要添加 Microsoft.Extensions.Hosting.Systemd NuGet 包:

  1. dotnet add package Microsoft.Extensions.Hosting.Systemd 

然后,我们需要修改 Program.cs 中的 CreateHostBuilder 方法,添加 UseSystemd 方法调用,将宿主(Host)生命周期设置为 Microsoft.Extensions.Hosting.Systemd.SystemdLifetime,以便应用程序可以接收启动和停止信号,并配置控制台输出记录为 systemd 格式。

  1. public static IHostBuilder CreateHostBuilder(string[] args) => 
  2.     Host.CreateDefaultBuilder(args) 
  3.         .UseSystemd() // Sets the host lifetime to Microsoft.Extensions.Hosting.Systemd.SystemdLifetime... 
  4.         .ConfigureServices((hostContext, services) => 
  5.         { 
  6.             services.AddHostedService<Worker>(); 
  7.         }) 
  8.         .UseSerilog(); //将 Serilog 设置为日志提供程序 

重新运行以下命令将程序发布到文件夹:

  1. dotnet publish -c Release -r linux-x64 -o c:\test\workerpub\linux 

然后重复前面的步骤,在 Xshell 中使用 rz 命令将应用程序复制到测试机,并为 /srv/Worker/MyService 文件分配可执行权限。

§配置文件

接下来我们需要创建配置文件,将服务的有关信息告知 systemd,以便它知道如何运行此服务。为此,我们需要创建一个 .service 文件,我们将在注册和运行此服务的 Linux 机器上使用该文件。

在我们的项目中创建一个名为 MyService.service 的服务单元配置文件,内容如下:

  1. [Unit] 
  2. Description=Long running service/daemon created from .NET worker template 
  3.  
  4. [Service] 
  5. # The systemd service file must be configured with Type=notify to enable notifications. 
  6. Type=notify 
  7. # will set the Current Working Directory (CWD). Worker service will have issues without this setting 
  8. WorkingDirectory=/srv/Worker 
  9. # systemd will run this executable to start the service 
  10. ExecStart=/srv/Worker/MyService 
  11. to query logs using journalctl, set a logical name here   
  12. SyslogIdentifier=MyService 
  13.  
  14. # Use your username to keep things simple. 
  15. # If you pick a different user, make sure dotnet and all permissions are set correctly to run the app 
  16. To update permissions, use 'chown yourusername -R /srv/Worker' to take ownership of the folder and files, 
  17. #       Use 'chmod +x /srv/Worker/MyService' to allow execution of the executable file 
  18. User=yourusername 
  19.  
  20. # This environment variable is necessary when dotnet isn't loaded for the specified user
  21. To figure out this value, run 'env | grep DOTNET_ROOT' when dotnet has been loaded into your shell. 
  22. Environment=DOTNET_ROOT=/usr/share/dotnet/dotnet 
  23.  
  24. # This gives time to MyService to shutdown gracefully. 
  25. TimeoutStopSec=300 
  26.  
  27. [Install] 
  28. WantedBy=multi-user.target 

使用时应将 User=yourusername 项中的 yourusername 改为具体的 linux 系统的登录名。

Systemd 期望所有的配置文件放置在 /etc/systemd/system/ 目录下,我们打开此目录,并使用 rz 命令将服务配置文件复制到 /etc/systemd/system/MyService.service,

  1. cd /etc/systemd/system/ 
  2.  
  3. rz 

然后执行以下命令让 systemd 重新加载配置文件:

  1. systemctl daemon-reload 

§管理服务

之后,可以运行以下命令来检查 systemd 是否识别了我们的服务:

  1. systemctl status MyService 

结果显示如下:

这表明我们注册的新服务被禁用了,可以通过运行以下命令来启动它:

  1. systemctl start MyService 

重新运行 systemctl status MyService 命令查看服务状态,显示如下:

停止服务可以运行以下命令:

  1. systemctl stop MyService 

如果您希望该服务在开机时自动启动,那么可以运行以下命令:

  1. systemctl enable MyService 

禁用开机自动启动,可以运行以下命令:

  1. systemctl disable MyService 

查看服务是否开机自动启动,可以运行以下命令:

  1. systemctl is-enabled MyService 

§Systemd 服务日志

命令 journalctl 可以用来查看 systemd 收集的日志。systemd-journald 服务负责 systemd 的日志收集,它从内核、systemd 服务和其他源检索信息。日志的集中收集,有利于对其进行检索查询。journal 中的日志记录是结构化和有索引的,因此 journalctl 能够以各种有用的格式来展现日志信息。

我们可以使用 journalctl 命令来验证应用程序是否成功运行,因为该命令可以跟踪显示应用程序的输出信息:

  1. journalctl -u MyService -f 

按 Ctrl-C 退出命令。

当我们在程序中调用 UseSystemd 方法时,会将 Extensions.LogLevel 映射到 Syslog 日志级别:

LogLevel Syslog level systemd name
Trace/Debug 7 debug
Information 6 info
Warning 4 warning
Error 3 err
Critical 2 crit

所以,我们可以使用 journalctl 命令的优先级标记(priority-flag)-p 来根据日志级别过滤应用程序的输出信息:

  1. journalctl -p 4 -u MyService -f 

总结

在本文中,我通过一个实例详细介绍了如何将 .NET Worker Service 部署到 Linux 系统作为 Systemd Service 运行,并说明了如何使用 systemctl 命令来管理服务,如何使用 journalctl 命令查看 Systemd 服务日志。

当我们向 HostBuilder 添加了 .UseSystemd() 方法调用后,编译出的程序,既可以作为 Linux 控制台应用运行,也可以作为 Systemd Service 运行。

您可以从 GitHub 下载本文中的源码。

参考:

https://swimburger.net/blog/dotnet/how-to-run-a-dotnet-core-console-app-as-a-service-using-systemd-on-linux

https://devblogs.microsoft.com/dotnet/net-core-and-systemd/

https://docs.microsoft.com/zh-cn/dotnet/core/tools/dotnet-publish

https://www.freedesktop.org/wiki/Software/systemd/

https://systemd.io/

https://www.linode.com/docs/guides/how-to-use-journalctl/

https://github.com/ITTranslate/WorkerServiceAsWindowsService 前篇文章源码

 

https://github.com/ITTranslate/WorkerServiceAsSystemdService 本文源码

 

责任编辑:武晓燕 来源: 技术译站
相关推荐

2022-04-26 09:16:07

PWA线程生命周期

2023-10-31 15:08:56

WorkBoxServiceWorker

2009-03-25 09:44:46

IBM云计算智慧地球

2021-03-03 08:18:54

Service组件

2009-11-27 13:45:02

Tomcat for

2010-12-24 09:36:15

部署Silverlig

2009-10-13 09:33:49

VB.NET Web

2009-10-29 09:06:26

VB.NET Web

2009-10-13 11:22:46

VB.NET调用Web

2009-10-13 10:21:58

VB.NET实现Web

2017-10-18 15:28:08

Service WorPWA离线

2009-07-27 09:07:04

Profile SerASP.NET AJA

2009-07-27 17:32:39

Web ServiceASP.NET

2009-10-29 11:26:28

VB.NET调用Web

2009-07-02 16:36:58

Python程序

2010-03-04 10:50:45

windows ser

2021-09-11 15:36:08

AWS云服务Amazon

2021-06-02 08:07:59

LinuxService应用

2009-12-30 15:50:18

ADO.NET Dat

2021-06-04 06:20:47

systemd定位工具系统运维
点赞
收藏

51CTO技术栈公众号