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

上一篇文章我们了解了如何将 .NET Worker Service 作为 Windows 服务运行,今天我接着介绍一下如何将 Worker Service 部署到 Linux 上,并作为 Systemd Service 运行。

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

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

创建项目并发布

  • § 下载 Worker Service 源码

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

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

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

dotnet build

  • § 删除用不到的依赖项

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

dotnet remove package Microsoft.Extensions.Hosting.WindowsServices

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

  • § 修改配置文件

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

{
  "Name": "RollingFile",
  "Args": {
    "pathFormat": "Logs/{Hour}.log",
    "outputTemplate": "{Timestamp:o} [{Level:u3}] ({MachineName}/{ProcessId}/{ProcessName}/{ThreadId}) {Message}{NewLine}{Exception}"
  }
},
{
  "Name": "SQLite",
  "Args": {
    "sqliteDbPath": "Logs/log.db",
    "tableName": "Logs",
    "maxDatabaseSize": 1,
    "rollOver": true
  }
}

这是因为 Windows 中使用反斜杠 \ 来表示目录,而 Linux 中使用正斜杠 / 来表示目录。
假如不修改保存路径,您将会看到日志被保存成如下的尴尬文件名:

‘Logs\2021061715.log’
‘Logs\log.db’

  • § 发布程序

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

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 目录:

mkdir /srv/Worker

使用 rz 命令将 linux.zip 复制到测试机,
在这里插入图片描述
然后在测试机上解压 linux.zip 到 /srv/Worker 目录:

unzip linux.zip -d /srv/Worker

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

-# 分配可执行权限
chmod +x /srv/Worker/MyService
-# 运行
/srv/Worker/MyService

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

作为 Systemd Service 运行

  • § 添加 Systemd Service 依赖

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

dotnet add package Microsoft.Extensions.Hosting.Systemd

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

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

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

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

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

  • § 配置文件

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

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

[Unit]
Description=Long running service/daemon created from .NET worker template

[Service]
# The systemd service file must be configured with Type=notify to enable notifications.
Type=notify
# will set the Current Working Directory (CWD). Worker service will have issues without this setting
WorkingDirectory=/srv/Worker
# systemd will run this executable to start the service
ExecStart=/srv/Worker/MyService
# to query logs using journalctl, set a logical name here  
SyslogIdentifier=MyService

# Use your username to keep things simple.
# If you pick a different user, make sure dotnet and all permissions are set correctly to run the app
# To update permissions, use 'chown yourusername -R /srv/Worker' to take ownership of the folder and files,
#       Use 'chmod +x /srv/Worker/MyService' to allow execution of the executable file
User=yourusername

# This environment variable is necessary when dotnet isn't loaded for the specified user.
# To figure out this value, run 'env | grep DOTNET_ROOT' when dotnet has been loaded into your shell.
Environment=DOTNET_ROOT=/usr/share/dotnet/dotnet

# This gives time to MyService to shutdown gracefully.
TimeoutStopSec=300

[Install]
WantedBy=multi-user.target

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

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

cd /etc/systemd/system/
rz

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

systemctl daemon-reload

  • § 管理服务

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

systemctl status MyService

结果显示如下:
在这里插入图片描述
这表明我们注册的新服务被禁用了,可以通过运行以下命令来启动它:

systemctl start MyService

重新运行 systemctl status MyService 命令查看服务状态,显示如下:
在这里插入图片描述
停止服务可以运行以下命令:

systemctl stop MyService

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

systemctl enable MyService

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

systemctl disable MyService

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

systemctl is-enabled MyService

  • § Systemd 服务日志

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

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

journalctl -u MyService -f
按 Ctrl-C 退出命令。

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

LogLevelSyslog levelsystemd name
Trace/Debug7debug
Information6info
Warning4warning
Error3err
Critical2crit

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

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 本文源码

相关阅读:

作者 : 技术译民
出品 : 技术译站

### 回答1: To publish a .NET Worker Service from a Windows system to a Linux system, you can follow these general steps: 1. Compile the .NET Worker Service for Linux: You can use the .NET Core CLI tool or Visual Studio to compile your Worker Service for Linux. Make sure you target the appropriate runtime, which can be Linux-x64, Linux-arm, or other Linux architectures. 2. Create a package: Create a package of your compiled Worker Service using the "dotnet publish" command. This will create a directory containing all the files required to run the Worker Service on a Linux system. 3. Transfer the package to the Linux system: You can use various methods to transfer the package to the Linux system, such as SCP, FTP, or Samba file sharing. 4. Install .NET runtime on the Linux system: If the Linux system does not have the .NET runtime installed, you need to install it before running the Worker Service. You can use the package manager of your Linux distribution to install the runtime. 5. Run the Worker Service: You can start the Worker Service by navigating to the directory containing the published files on the Linux system and running the command "dotnet YourWorkerService.dll". Note that some adjustments may be necessary to make the Worker Service compatible with the Linux environment, such as using appropriate file paths, handling differences in file systems, and configuring system services. Also, make sure that the Linux system meets the requirements of the .NET runtime version used to compile the Worker Service. ### 回答2: 要将Windows系统上的Worker Service发布到Linux系统上,首先需要将Worker Service的代码从Windows环境迁移到Linux环境。这是因为Windows和Linux使用了不同的操作系统核心和硬件体系结构,所以代码需要相应的修改和调整。 在迁移代码之前,需确定Worker Service使用的是跨平台的编程语言和框架,例如.NET Core。如果Worker Service使用的是其他不支持跨平台的语言或框架,则需要将其重写为跨平台的版本。 在将代码迁移到Linux系统之后,还需要安装并配置Linux系统上的必要软件和依赖项,例如.NET Core运行时环境等。这些软件和依赖项可以通过包管理器或其他方式安装。 接下来,可以使用一种适合的部署工具,例如Docker,来将Worker Service打包为一个容器。容器化可以提供隔离和易于管理的好处。 最后,可以将打包好的容器部署Linux系统上,运行Worker Service。这可以通过命令行或图形化界面实现,具体取决于系统和个人偏好。 在部署过程中,可能会遇到一些问题和挑战,例如平台差异、依赖项冲突等。因此,建议事先做好充分的测试和调试工作,确保Worker ServiceLinux系统上能够正常运行。 总之,将Windows系统上的Worker Service发布到Linux系统上需要进行代码迁移、环境配置和部署步骤。通过适当的准备和措施,可以成功实现这一目标。 ### 回答3: 要将Windows系统中的WorkerService发布到Linux系统上,需要进行一些准备工作和配置步骤。 首先,需要将WorkerService的代码进行适配和调整,以确保其在Linux系统上能够正常运行。这可能涉及到修改文件路径、处理文件系统相关的差异、更改对操作系统的依赖等等。确保代码适配是成功迁移的关键。 接下来,需要在Linux系统上安装合适的启动脚本和依赖库,以确保WorkerService的正常运行。首先,需要安装mono运行时环境,它是在Linux系统上运行基于.NET框架的应用程序的重要组件。然后,可以编写启动脚本(如Shell脚本)来控制WorkerService的启动和停止,并将该脚本添加到系统服务中使其在系统启动时自动启动。此外,可能还需要安装其他应用程序所需的依赖库。 在发布到Linux系统之前,还需要进行一些测试工作,确保WorkerService在新环境中能够正常工作。测试期间,需要注意记录任何可能出现的错误、异常或兼容性问题,并进行相应的调整和修复。 最后,在发布到Linux系统之前,需要选择合适的Linux发行版和版本,并确保系统上已经正确地安装了所需的操作系统和软件依赖。这可以通过在Linux系统上运行适配后的WorkerService的二进制文件来进行验证。 总体而言,发布WorkerServiceLinux系统涉及到代码适配、安装运行时环境和依赖库、编写启动脚本,并进行测试和验证等一系列步骤。只有确保这些步骤正确执行,才能顺利地将WorkerService从Windows系统发布到Linux系统。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值