본문 바로가기
C#

[C#-Linux] 워커 서비스 프로그램 서비스로 등록하기

by Jcoder 2021. 10. 21.

1. .NET 5 Work Service 생성

2.

  • nuget에서 Microsoft.Extensions.Hosting.Systemd 설치
  • program.cs - .UseSystemd() 추가
        public class Program
        {
            /*
                [서비스 등록]
                sudo dotnet ./Worker_Service.dll --install
                sudo dotnet ./Worker_Service.dll -i
                [서비스 해제]
                sudo dotnet ./Worker_Service.dll --uninstall
                sudo dotnet ./Worker_Service.dll -u
                [서비스 시작]
                sudo systemctl start dotnet-worker_Service
                [서비스 중지-1 SIGINT]
                sudo systemctl stop dotnet-worker_Service
                [서비스 중지-2 SIGTERM]
                sudo systemctl kill dotnet-worker_Service
                [로그 보기]
                sudo journalctl -u dotnet-worker_Service
             */
            public static void Main(string[] args)
            {
                if (args.Length >= 1)
                {
                    string netDllPath = typeof(Program).Assembly.Location;
    
                    if (args[0] == "--install" || args[0] == "-i")
                    {
                        InstallService(netDllPath, true);
                    }
                    else if (args[0] == "--uninstall" || args[0] == "-u")
                    {
                        InstallService(netDllPath, false);
                    }
    
                    return;
                }
    
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .UseSystemd()
                    .ConfigureServices((hostContext, services) =>
                    {
                        services.AddHostedService<Worker>();
                    });
    
            static int InstallService(string netDllPath, bool doInstall)
            {
                // 2021-04-22
                // remove: KillSignal=SIGINT
                // added: KillMode=mixed
                string serviceFile = @"
    [Unit]
    Description={0} running on {1}
    [Service]
    WorkingDirectory={2}
    ExecStart={3} {4}
    SyslogIdentifier={5}
    KillMode=mixed
    [Install]
    WantedBy=multi-user.target
    ";
    
                string dllFileName = Path.GetFileName(netDllPath);
                string osName = Environment.OSVersion.ToString();
    
                FileInfo fi = null;
    
                try
                {
                    fi = new FileInfo(netDllPath);
                }
                catch { }
    
                if (doInstall == true && fi != null && fi.Exists == false)
                {
                    WriteLog("NOT FOUND: " + fi.FullName);
                    return 1;
                }
    
                string serviceName = "dotnet-" + Path.GetFileNameWithoutExtension(dllFileName).ToLower();
    
                string exeName = Process.GetCurrentProcess().MainModule.FileName;
    
                string workingDir = Path.GetDirectoryName(fi.FullName);
                string fullText = string.Format(serviceFile, dllFileName, osName, workingDir,
                        exeName, fi.FullName, serviceName);
    
                string serviceFilePath = $"/etc/systemd/system/{serviceName}.service";
    
                if (doInstall == true)
                {
                    File.WriteAllText(serviceFilePath, fullText);
                    WriteLog(serviceFilePath + " Created");
                    ControlService(serviceName, "enable");
                    ControlService(serviceName, "start");
                }
                else
                {
                    if (File.Exists(serviceFilePath) == true)
                    {
                        ControlService(serviceName, "stop");
                        File.Delete(serviceFilePath);
                        WriteLog(serviceFilePath + " Deleted");
                    }
                }
    
                return 0;
            }
    
            static int ControlService(string serviceName, string mode)
            {
                string servicePath = $"/etc/systemd/system/{serviceName}.service";
    
                if (File.Exists(servicePath) == false)
                {
                    WriteLog($"No service: {serviceName} to {mode}");
                    return 1;
                }
    
                ProcessStartInfo psi = new ProcessStartInfo();
                psi.FileName = "systemctl";
                psi.Arguments = $"{mode} {serviceName}";
                using Process child = Process.Start(psi);
                child.WaitForExit();
                return child.ExitCode;
            }
    
            static void WriteLog(string text)
            {
                Console.WriteLine(text);
            }
        }

3. 프로그램 등록, 시작, 중지, 삭제

    $cd /usr/local/Worker_Service
    [서비스 등록]
    $sudo dotnet ./Worker_Service.dll --install
    $sudo dotnet ./Worker_Service.dll -i

    [서비스 해제]
    $sudo dotnet ./Worker_Service.dll --uninstall
    $sudo dotnet ./Worker_Service.dll -u

    [서비스 시작]
    $sudo systemctl start dotnet-worker_service

    [서비스 중지-1 SIGINT]
    $sudo systemctl stop dotnet-worker_service

    [서비스 중지-2 SIGTERM]
    $sudo systemctl kill dotnet-worker_service

    [로그 보기]
    $sudo journalctl -u dotnet-worker_service

 

 

참고 : https://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0&detail=1&wid=12608

 

.NET Framework: 1044. C# - Generic Host를 이용해 .NET 5로 리눅스 daemon 프로그램 만드는 방법

글쓴 사람 정성태 (techsharer at outlook.com) 홈페이지 첨부 파일 부모글 보이기/감추기 C# - Generic Host를 이용해 .NET 5로 리눅스 daemon 프로그램 만드는 방법 지난번에는 별다른 의존성 없이 단순하게 만

www.sysnet.pe.kr