简体   繁体   English

如何从 ASP.NET 创建 PID 文件 Linux 下的核心应用

[英]How to create PID file from ASP.NET Core application under Linux

I wrote an ASP.NET Core application (.NET 5 actually) and run it under Linux as a systemd service (following this Microsoft guide ).我写了一个 ASP.NET Core 应用程序(实际上是 .NET 5)并在 Linux 下作为系统服务运行它(遵循这个 Microsoft 指南)。 Then I wanted to monitor this application with monit application.然后我想用monit application来监控这个应用程序。 This application requires services to create a PID file so they are easily discoverable.此应用程序需要服务来创建 PID 文件,以便它们很容易被发现。 I decided I'll write a Q&A-style question to help others achieve the same faster.我决定写一个问答式的问题来帮助其他人更快地实现同样的目标。

Note: the solution described here is a part of my NuGet package with open source available on github in case you prefer to achieve your goal the package way.注意:此处描述的解决方案是我的NuGet package的一部分,如果您更喜欢通过 package 方式实现目标,可以在 github上获得开源。

IHostedService托管服务

There are a few ways in .NET Core to run a background task. .NET Core 中有几种运行后台任务的方法。 IHostedService is one of them that contains StartAsync method which, after a service is registered, is called on the startup. IHostedService是其中之一,它包含StartAsync方法,该方法在服务注册后在启动时调用。 The interface also defines StopAsync which is called on a graceful shutdown.该接口还定义了在正常关闭时调用的StopAsync Visit this Microsoft page for more details on IHostedService .有关IHostedService的更多详细信息,请访问此 Microsoft 页面

Knowing that we can create our own IHostedService that will manage the PID file of our application:知道我们可以创建自己的 IHostedService 来管理我们应用程序的 PID 文件:

public class PidFileHostedService : IHostedService
{
    private readonly ILogger<PidFileHostedService> logger;
    private readonly IConfiguration configuration;
    private readonly IWebHostEnvironment env;

    private bool isPidFileCreated = false;
    private string pidFile = string.Empty;

    public PidFileHostedService(ILogger<PidFileHostedService> logger,
        IConfiguration configuration,
        IWebHostEnvironment env)
    {
        this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
        this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
        this.env = env ?? throw new ArgumentNullException(nameof(env));
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        try
        {
            if (env.IsDevelopment())
                return;

            pidFile = configuration.GetValue<string>("PidFile");

            if (string.IsNullOrWhiteSpace(pidFile))
                return;

            await WritePidFile();
            
            isPidFileCreated = true;
        }
        catch (Exception ex)
        {
            logger.LogError(ex, $"Unexpected error when starting {nameof(PidFileHostedService)}", null);
        }
    }

    private async Task WritePidFile()
    {
        var processId = Environment.ProcessId.ToString();
        await File.WriteAllTextAsync(pidFile, processId);
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        try
        {
            if (isPidFileCreated)
                File.Delete(pidFile);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Unexpected error when deleting PID file", null);
        }
        
        return Task.CompletedTask;
    }
}

This service assumes there is the PidFile property in the appsettings.json file of an application.此服务假定应用程序的 appsettings.json 文件中存在PidFile属性。 Do not forget to register the service in the Startup.cs:不要忘记在 Startup.cs 中注册服务:

services.AddHostedService<PidFileHostedService>();

Service file changes服务文件更改

As I wrote in the question I used Microsoft guide on how to make my app run as a systemd service .正如我在问题中所写,我使用了关于如何让我的应用程序作为系统服务运行的 Microsoft 指南 Now, after the changes, the service has to have necessary permissions to the directory in which it will create the PID file.现在,在更改之后,该服务必须对将在其中创建 PID 文件的目录具有必要的权限。 Creation of this directory with necessary permission can be delegated to systemd.可以将具有必要权限的此目录的创建委托给 systemd。 It is enough to add this line to the service file under [Service] section:将此行添加到[Service]部分下的服务文件中就足够了:

RuntimeDirectory=helloapp

Thanks to this line systemd will create helloapp subdirectory in /var/run on every service start with necessary permissions.由于这一行,systemd 将在每个服务启动时在/var/run中创建helloapp子目录,并具有必要的权限。 It is also a good idea to add the following line to the same section which will tell systemd to double check the PID file is deleted after the app is stopped:将以下行添加到同一部分也是一个好主意,它将告诉 systemd 仔细检查应用程序停止后是否删除了 PID 文件:

PIDFile=/var/run/helloapp/helloapp.pid

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM