.NET 6 Linux 系统服务 Systemd (案例版)

.Net Core Windows 系统服务,之前已经写过了,但是,对于Linux的系统服务,却没有写过,主要是因为,大部分Linux的.Net服务都直接Docker了,当然,不排除有这种使用的,可能搞成启动执行了,也有可能用守护进程的方式搞,但是,Systemd这种系统服务的方式,还是十分推荐的。.

那么就写一篇基于Linux Systemd 系统服务的案例

创建.Net 6 WorkServer

.NET 6 Linux 系统服务 Systemd (案例版)

我这里选了不使用.NET 6 特有的统一命名空间方式,就以旧方式编码。

.NET 6 Linux 系统服务 Systemd (案例版)

默认创建完,是这个样子的

.NET 6 Linux 系统服务 Systemd (案例版)

添加Systemd 系统服务

Install-Package Microsoft.Extensions.Hosting.Systemd

然后,修改 Program方法为以下的方法,主要是增加了UseSystemd服务

public class Program
{
    public static void Main(string[] args)
    {
        IHost host = Host.CreateDefaultBuilder(args)
            .UseSystemd()//新增的 .UseSystemd()服务
            .ConfigureServices(services =>
            {
                services.AddHostedService<Worker>();
            })
            .Build();

        host.Run();
    }
}

修改WorkServer逻辑

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
        Log.Info($"后台服务初始化!");
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _ = Task.Run(async () =>
            {
                while (!stoppingToken.IsCancellationRequested)
                {
                    Log.Info($"后台服务运行: {DateTime.Now}");
                    await Task.Delay(1000, stoppingToken);
                }
            }, stoppingToken);
        await Task.CompletedTask;
    }
    public override Task StopAsync(CancellationToken cancellationToken)
    {
        base.StopAsync(cancellationToken);
        Log.Info("系统服务停止!");
        return Task.CompletedTask;
    }
}

Linux 执行脚本

因为我感觉敲命令,老麻烦了(用惯了Windows),所以,还是简单点,提供了一些命令的脚本

WorkerServiceDemo.service

这个是Linux系统服务的标准名称,后缀是固定的.service

[Unit]
Description= WorkerServiceDemo

[Service]
Type=notify
ExecStart=/usr/bin/dotnet  /home/kesshei/Desktop/WorkerServiceDemo/WorkerServiceDemo.dll

[Install]
WantedBy=multi-user.target

initserver.sh

初始化服务,也叫安装服务,目的是把上面的 WorkerServiceDemo.service 服务文件拷贝到 /etc/systemd/system 系统服务路径下

系统服务下的服务还是挺多的

.NET 6 Linux 系统服务 Systemd (案例版)
#!/bin/bash
ServerPath='/etc/systemd/system'
FileName='WorkerServiceDemo.service'

chmod +x start.sh
chmod +x stop.sh
chmod +x uninstallService.sh

cp $FileName $ServerPath/$FileName
echo 'copy success'
./start.sh
echo 'Server Init Success'

这个脚本,顺便把其他的sh授权了,所以, initserver.sh 文件要自己先给它授权,要不然,用不了 chmod +x initserver.sh 即可。

start.sh

启动服务

#!/bin/bash
sudo su - <<EOF
systemctl daemon-reload
systemctl start WorkerServiceDemo.service
systemctl enable WorkerServiceDemo.service
echo 'Server start Success'
EOF

stop.sh

停止服务

#!/bin/bash
sudo su - <<EOF
systemctl stop WorkerServiceDemo.service
systemctl disable WorkerServiceDemo.service
echo 'Server stop Success'
EOF

uninstallService.sh

卸载服务,基本与安装服务相反的方向

#!/bin/bash
sudo su - <<EOF
systemctl stop WorkerServiceDemo.service
systemctl disable WorkerServiceDemo.service
rm /etc/systemd/system/WorkerServiceDemo.service
systemctl daemon-reload

echo 'uninstallserver success'
EOF

项目部署到Linux下

我目前使用的linux是 Ubantu 18.4,但是,命令应该是类似的。

我直接复制Bin目录下的项目到Linux上

我到脚本目录下 /home/kesshei/Desktop/WorkerServiceDemo/Script

执行第一个命令

chmod +x initserver.sh

执行第二个命令

sudo ./initserver.sh

然后 输出,当然,也会让你输入root的密码

copy success
Created symlink /etc/systemd/system/multi-user.target.wants/WorkerServiceDemo.service → /etc/systemd/system/WorkerServiceDemo.service.
Server start Success
Server Init Success

没有啥异常,就说明,服务启动OK了。

同时,也要查看服务的日志目录是否有日志,来查看服务是否正常

下面这个路径:

/home/kesshei/Desktop/WorkerServiceDemo/Logs

我这边已经有了一个文件了

.NET 6 Linux 系统服务 Systemd (案例版)

也看到日志内容了。

停止服务

./stop.sh

输出以下内容

Removed /etc/systemd/system/multi-user.target.wants/WorkerServiceDemo.service.
Server stop Success

说明正常

同时也看到了,停止服务的消息,跟我们的业务逻辑是一致的。

.NET 6 Linux 系统服务 Systemd (案例版)

启动服务

./start.sh

输出以下内容

Created symlink /etc/systemd/system/multi-user.target.wants/WorkerServiceDemo.service → /etc/systemd/system/WorkerServiceDemo.service.
Server start Success

说明正常

同时也看到了,启动服务的消息,跟我们的业务逻辑也是一致的。

.NET 6 Linux 系统服务 Systemd (案例版)

重启系统后

可以看到,它自己是启动服务的。

.NET 6 Linux 系统服务 Systemd (案例版)

总结

至此,Windows的系统服务和Linux的系统服务两种原生实现方式都实现了。

还是很不错的说。

代码地址

https://github.com/kesshei/WorkerServiceDemo.git

https://gitee.com/kesshei/WorkerServiceDemo.git