zoukankan      html  css  js  c++  java
  • .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 中使用正斜杠 / 来表示目录。

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

    'Logs2021061715.log'
    'Logslog.db'
    

    发布程序

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

    dotnet publish -c Release -r linux-x64 -o c:	estworkerpublinux
    

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

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

    作为 Linux 控制台程序运行

    将文件夹 C: estworkerpublinux 下的文件压缩为 linux.zip

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

    mkdir /srv/Worker
    

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

    copy files to linux

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

    unzip linux.zip -d /srv/Worker
    

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

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

    run as console on linux

    按下 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:	estworkerpublinux
    

    然后重复前面的步骤,在 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 status MyService

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

    systemctl start MyService
    

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

    systemctl status MyService 2

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

    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 日志级别:

    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 来根据日志级别过滤应用程序的输出信息:

    journalctl -p 4 -u MyService -f
    

    总结

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

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

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

    参考:


    相关阅读:

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

    © 转载请标明出处   https://www.cnblogs.com/ittranslator

    不做标题党,只分享技术干货

    公众号『技术译站』,欢迎扫码关注

  • 相关阅读:
    bootstrap table load属性
    Jquery中hide()、show()、remove()特性
    Jquery精准计算
    .nojekyll 文件是什么
    快来用 Nuxt 开发静态网站
    CI:持续集成
    把组件库发布到 npm
    JS的各种模块化规范
    打包发布:让组件库支持按需加载
    docz: 组件库文档 so easy!
  • 原文地址:https://www.cnblogs.com/ittranslator/p/worker-service-as-systemd-services-on-linux.html
Copyright © 2011-2022 走看看