透過 .NET Core 3.0,提供的便利套件,我們可以快速的開發出 Windows Services 或 Linux systemd,擴展 .NET Core 的應用領域。

背景資訊

現在的 .NET Core 版本為 v3.0.0-preview8。

專案的執行環境

  • SDK 3.0.100-preview8-013656
  • VSCode 1.37
  • Windows 10
  • CentOS 7

到這裡安裝 .NET Core SDK 3.0
(透過安裝 preview 版 的 Visual Studio 也可以建立 .NET Core 3 的服務專案)

Windows Services 範例

利用 dotnet cli 建立服務專案

.NET Core 3.0 提供了 worker 範本,用來建立系統服務的基本專案。

在新增的專案目錄中,執行

1
dotnet new worker

輸出如下:

1
2
3
4
5
6
7
The template "Worker Service" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on D:\Temp\netcore\netcorewinsrv\netcorewinsrv.csproj...
D:\Temp\netcore\netcorewinsrv\netcorewinsrv.csproj 的還原於 260.69 ms 完成。

Restore succeeded.

安裝 WindowsServices 套件

此時此刻,最新版本為 3.0.0-preview8.19405.4

1
dotnet add package Microsoft.Extensions.Hosting.WindowsServices --version 3.0.0-preview8.19405.4

啟用 WindowsService 功能

增加 UseWindowsService() 到 Program.cs 的 HostBuilder 中,以啟用 WindowsService 功能。

1
2
3
4
5
6
7
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});

實做功能

修改 Worker.cs 實做要提供的功能。

範例中,每秒輸出時間到 /var/log/netcoreservice.log 這個檔案中。

1
2
3
4
5
6
7
8
9
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
File.AppendAllText("/var/log/netcoreservice.log",
$"Worker running at: {DateTimeOffset.Now}{Environment.NewLine}");
await Task.Delay(1000, stoppingToken);
}
}

安裝為 Services

發佈專案

或是建置(build),兩者輸出路徑不同,到時要建立 Services 時,指的路徑也不同。

1
dotnet publish -o d:\Temp\workerpub

輸出

1
2
3
4
5
6
7
8
9
10
D:\GitHubRepo\net-core-3-windows-services>dotnet publish -o d:\Temp\workerpub
Microsoft (R) Build Engine for .NET Core 16.3.0-preview-19377-01+dd8019d9e 版
Copyright (C) Microsoft Corporation. 著作權所有,並保留一切權利。

D:\GitHubRepo\net-core-3-windows-services\net-core-3-windows-services.csproj 的還原於 26.1 ms 完成。
You are using a preview version of .NET Core. See: https://aka.ms/dotnet-core-preview
net-core-3-windows-services -> D:\GitHubRepo\net-core-3-windows-services\bin\Debug\netcoreapp3.0\net-core-3-windows-services.dll
net-core-3-windows-services -> d:\Temp\workerpub\

D:\GitHubRepo\net-core-3-windows-services>

安裝 Services

在以 系統管理員 權限執行的 命令提示字元中,利用 windows 提供的 sc 命令安裝服務,命名為 “workertest”。binPath 參數則指向輸出的執行檔。

1
sc create workertest binPath=D:\Temp\workerpub\net-core-3-windows-services.exe

結果
安裝服務成功

啟用 Services

1
sc start workertest

服務執行中

可觀察 /var/log/netcoreservice.log 更新的狀態。

Linux systemd 範例

利用 dotnet cli 建立服務專案

安裝 Systemd 套件

此時此刻,最新版本為 3.0.0-preview8.19405.4

1
dotnet add package Microsoft.Extensions.Hosting.Systemd --version 3.0.0-preview8.19405.4

啟用 Systemd 功能

增加 UseSystemd() 到 Program.cs 的 HostBuilder 中,以啟用 Systemd 功能。

1
2
3
4
5
6
7
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});

實做功能

修改 Worker.cs 實做要提供的功能。

安裝為 Services

發佈專案

或是建置(build),兩者輸出路徑不同,到時要建立 Services 時,指的路徑也不同。

1
sudo dotnet publish -o /usr/sbin/testapp

建立 .service 檔

要建立 Linux 的 service,需要在 /etc/systemd/system/ 目錄下提供一個 .service 檔做配置 service 之用。將服務命名為 testapp 時,檔名為 testapp.service,基本內容如下

1
2
3
4
5
6
7
8
9
[Unit]
Description=my test app

[Service]
Type=notify
ExecStart=/usr/sbin/testapp/net-core-3-linux-systemd

[Install]
WantedBy=multi-user.target

ExecStart 指到發佈路徑下的主程式

重載服務

1
sudo systemctl daemon-reload

啟用 Services

1
sudo systemctl enable testapp.service

執行 Services

1
sudo systemctl enable testapp.service

觀察 /var/log/netcoreservice.log 的內容。

1
tail -f /var/log/netcoreservice.log

完整範例專案

Windows Services
GitHub: .NET Core 3 的 Windows Services 範例

Linux systemd
GitHub: .NET Core 3 的 Linux systemd 範例

以上,開工吧!

參考資料及圖片來源

  1. dotnet new worker - Windows Services or Linux systemd services in .NET Core
  2. .NET Core and systemd