我编写了一个ASP.NET核心应用程序(实际上是.NET 5),并将它作为系统服务在Linux下运行(遵循此Microsoft指南)。然后,我想用莫尼特应用程序来监视这个应用程序。此应用程序需要服务来创建PID文件,以便很容易地发现它们。我决定写一个问答式的问题来帮助别人更快地完成同样的任务。
发布于 2022-02-27 13:17:48
注意:这里描述的解决方案是我的NuGet包和开放源码可在github上获得的一部分,以防您更喜欢以包的方式实现目标。
IHostedService
.NET核心中有几种运行后台任务的方法。IHostedService是其中之一,它包含StartAsync方法,在注册服务之后,该方法在启动时被调用。该接口还定义了StopAsync,这是在优雅关闭时调用的。有关此Microsoft页面的更多细节,请访问IHostedService。
知道我们可以创建自己的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;
}
}此服务假定应用程序的PidFile文件中有appsettings.json属性。不要忘记在Startup.cs中注册服务:
services.AddHostedService<PidFileHostedService>();服务文件更改
正如我在问题中所写的那样,我使用了关于如何使我的应用程序作为系统服务运行的Microsoft指南。现在,更改之后,服务必须对它将在其中创建PID文件的目录具有必要的权限。可以将具有必要权限的此目录的创建委托给systemd。将这一行添加到[Service]部分下的服务文件中就足够了:
RuntimeDirectory=helloapp由于这一行,systemd将在每个服务启动时以必要的权限在/var/run中创建/var/run子目录。在同一部分中添加以下行也是一个好主意,这将告诉systemd在应用程序停止后再次检查PID文件的删除情况:
PIDFile=/var/run/helloapp/helloapp.pidhttps://stackoverflow.com/questions/71285083
复制相似问题