How to Develop Linux systemd services with .NET Core Worker Service

การพัฒนาโปรแกรม Linux systemd services ด้วย .NET Core Worker Service

โดยปกติแล้วการพัฒนาโปรแกรมด้วย .NET Core สามารถทำได้หลายรูปแบบ เช่น

  • Console
  • Windows Application
  • Web Application
    – ASP .NET MVC
    – ASP .NET Razor Pages
    – ASP .NET WebAPI
    – Blazor Server
    – Blazor WebAssembly
  • Mobile Applcation (Xamarin)

นับตั้งแต่ .NET Core 3.0 เป็นต้นมา ไมโครซอฟท์ได้ประกาศให้ .NET Core สามารถพัฒนา Worker Service ได้ และได้เพิ่ม dotnet new template ของ Worker Service มาให้ด้วยคำสั่ง

dotnet new worker

เพื่อจะให้นักพัฒนาเป็นทางเลือกใช้สำหรับโปรแกรมที่ต้องการทำงานโดยอัตโนมัติและสามารถ Auto Start ได้ในขณะที่ Linux Server หรือ Windows Server บูทเครื่องโดยที่ไม่จำเป็นที่ต้อง Login ถ้าท่านคิดว่าต้้องการโปรแกรมที่ทำแบบนี้ได้ แนะนำให้เลือกใช้ Worker Service ครับ

บทความนี้เป็นวิธีการใช้ Linux Server เท่านั้น ส่วน Windows Server จะกล่าวในบทความถัดไป

เตรียมเครื่อง Linux Server

  1. ดาวน์โหลด .NET Core ได้ที่ https://dotnet.microsoft.com/download/dotnet-core ให้เลือกเวอร์ชั่นล่าสุดที่ (recommended)

  1. เลือกดาวน์โหลดไฟล์ .NET Core SDK หรือ Runtime ให้ตรงกับสถาปัตยกรรม CPU ที่ใช้เช่น x64

  1. กดปุ่ม Copy ที่ Direct link

  1. ไปที่เครื่อง Linux server แล้วดาวน์โหลดไฟล์ .NET Core SDK หรือ Runtime ได้ด้วยโปรแกรม wget หรือ curl เช่น

wget https://download.visualstudio.microsoft.com/download/pr/c4b503d6-2f41-4908-b634-270a0a1dcfca/c5a20e42868a48a2cd1ae27cf038044c/dotnet-sdk-3.1.101-linux-x64.tar.gz

  1. แตกไฟล์ .tar.gz ไปเก็บไว้ที่ /usr/share/dotnet

sudo mkdir /usr/share/dotnet
sudo tar xfz dotnet-sdk-3.1.101-linux-x64.tar.gz -C /usr/share/dotnet/

  1. เพิ่มคำสั่ง export ไว้ที่ไฟล์ .bashrc

export PATH=$PATH:/usr/share/dotnet
export DOTNET_ROOT=/usr/share/dotnet

สร้างโปรเจ็ค Worker Service

  1. ใช้โปรแกรม Visual Studio Code Remote เข้าไปที่เครื่อง Linux Server สามารถดูได้จากบทความนี้ Visual Studio Code Remote Development

e7cff47d11ad5c9108db06063de5524961754906_2_690x345

  1. สร้างโปรเจ็ค Worker Service ด้วยคำสั่ง dotnet new แล้วกดปุ่ม Open Folder เลือกโฟลเดอร์สร้างโปรเจ็ค แล้วกดปุ่ม OK

dotnet new worker -o CodeBangkok

  1. ติดตั้ง Microsoft.Extensions.Hosting.Systemd Package ได้ด้วยคำสั่ง

dotnet add package Microsoft.Extensions.Hosting.Systemd

  1. เปิดไฟล์ Program.cs แล้วเพิ่มคำสั่ง .UseSystemd() เข้าไปที่ CreateHostBuilder
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseSystemd()
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<Worker>();
        });

  1. ท่านสามารถพัฒนาโปรแกรมได้ทีไฟล์ Worker.cs โปรแกรมจะเรียก ExecuteAsync ทำงานวนลูปตลอดเวลาโดยมีคำสั่งให้รอ Delay (หน่วยเป็น ms เช่น 1000 คือ 1 วินาที) แล้วจะกลับมาทำใหม่ไปเรื่อยๆ

  1. คำสั่ง _logger คือคำสั่งที่ใช้สำหรับ log มีอยู่ด้วยกันดังนี้
  • Level 2 - LogCritical
  • Level 3 - LogError
  • Level 4 - LogWarning
  • Level 6 - LogInformation
  • Level 7 - LogDebug
    ซึ่ง Log Level นี้เราสามารถใช้คำสั่ง journalctl เพิ่อ filter log level ได้
  1. ทดสอบแก้ไขโปรแกรมที่ ExecuteAsync ให้แสดงข้อความ Log ทุกๆ 30 วินาที (1000 x 30 = 30000) ดังนี้
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        _logger.LogCritical("Log Critical at: {time}", DateTimeOffset.Now);
        _logger.LogError("Log Error at: {time}", DateTimeOffset.Now);
        _logger.LogWarning("Log Warning at: {time}", DateTimeOffset.Now);
        _logger.LogInformation("Log Information at: {time}", DateTimeOffset.Now);
        _logger.LogDebug("Log Debug at: {time}", DateTimeOffset.Now);
        await Task.Delay(30000, stoppingToken);                
    }
}
  1. รันโปรแกรมด้วยคำสั่ง dotnet run

dotnet run

ติดตั้ง .NET Core Worker Service ไปที่ systemd

  1. Publish โปรแกรมได้ด้วยคำสั่งนี้ แล้ว Move โฟลเดอร์ publish ไปไว้ที่ /usr/share/CodeBangkok

dotnet publish -c Release
sudo mv ./bin/Release/netcoreapp3.1/publish/ /usr/share/CodeBangkok

  1. สร้างไฟล์ codebangkok.service ที่ /etc/systemd/system/ ด้วยโปรแกรม vi

sudo vi /etc/systemd/system/codebangkok.service

2.1 ใช้โปรแกรม vi กดปุ่ม i เพื่อเข้าสู่โหมด insert แล้วกด Copy โค้ดนี้ไปวาง
/* คำสั่ง ExecStart ใช้สำหรับอ้างถึง Binary file ที่จะรัน */

[Unit]
Description=CodeBangkok

[Service]
Type=notify
ExecStart=/usr/share/CodeBangkok/CodeBangkok

[Install]
WantedBy=multi-user.target

2.2 ใช้โปรแกรม vi กดปุ่ม esc แล้วพิมพ์ :wq แล้วกด enter

  1. รันคำสั่ง systemctl เพื่อ Reload Daemon และตรวจสอบสถานะได้ด้วยคำสั่ง

sudo systemctl daemon-reload
sudo systemctl status codebangkok

ดูจากสถานะจะเห็นว่าอยู่ในสถานะ loaded แต่ยัง inactive (dead) อยู่ (ออกหน้าจอนี้ได้ด้วยกดปุ่ม q)

  1. สั่ง Start CodeBangkok Service และเช็คสถานะได้ด้วยคำสั่งนี้ จะเห็นว่าสถานะถูกเปลี่ยนเป็น active (running) แล้ว

sudo systemctl start codebangkok
sudo systemctl status codebangkok

  1. กำหนดให้ CodeBangkok Service ทำงาน Auto Start ทุกครั้งที่ Boot เครื่องโดยไม่จำเป็นต้อง Login

sudo systemctl enable codebangkok

แต่ถ้าต้องการให้หยุดการ Auto Start ทำได้ด้วยคำสั่ง

sudo systemctl disable codebangkok

  1. ใช้คำสั่ง journalctl เพื่อดู log ได้ดังนี้

sudo journalctl -u codebangkok

  1. สามารถใช้ journalctl เพื่อ filter log level ได้ดังนี้
  • Level 2 - LogCritical
  • Level 3 - LogError
  • Level 4 - LogWarning
  • Level 6 - LogInformation
  • Level 7 - LogDebug
    เช่นต้องการดูเฉพาะ Level 3 - LogError

sudo journalctl -p 3 -u codebangkok

  1. ถ้าต้องการอัพเดตโปรแกรมอีกครั้งให้ copy ไฟล์ไปทับที่ /usr/share/CodeBangkok แล้วรันคำสั่งนี้อีกครั้ง

sudo systemctl daemon-reload
sudo systemctl start codebangkok

ที่มา: https://devblogs.microsoft.com/dotnet/net-core-and-systemd

ติดตาม CodeBangkok ได้ที่
Facebook Group: https://fb.com/groups/msdevth
Facebook Page: https://fb.com/codebangkok
Github: https://github.com/codebangkok

Donate ให้กับ CodeBangkok ได้ที่
BTC = 3GDxhb84ho2jmAV9seAgAFJ7dy1XR3GCyc
ETH = 0x119fa8A618A0283D1834853325A8FF4fe1101230
LTC = ME2abSdDeQYuTmzZSAnHL7LGGeF836d1ut
ZEC = t1Y4NkK3Dx3yBbwCVdpXzKYrqUSJSHgaFXa