I created a simple ASP.NET Core web application to run as a service on a Linux Ubuntu machine. When I run systemctl start webapp.service
to start the application, it starts fine. However, when I run systemctl stop webapp.service
to stop it, the command freezes for a long time and eventually times out. Looking at the application's stdout while it's stopping shows that it doesn't get past the await this.app.StopAsync()
statement. Here's the output:
Nov 21 08:59:57 LinxServer systemd[1]: Stopping WebApp...
Nov 21 08:59:57 LinxServer dotnet[6746]: info: Microsoft.Hosting.Lifetime[0]
Nov 21 08:59:57 LinxServer dotnet[6746]: Application is shutting down...
It's supposed to write "Stopped" after StopAsync()
returns, which doesn't happen.
However, when I run the application directly using the command do.net WebApplication1.dll
, it starts fine and when I press Ctrl+C, it shuts down as expected:
info: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
Stopping...
Stopped.
Here is the application code:
await Host
.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Application>();
})
.UseSystemd()
.Build()
.RunAsync();
class Application : IHostedService
{
private WebApplication app;
public async Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Starting...");
var builder = WebApplication.CreateBuilder();
builder.WebHost.UseKestrel(options => options.ListenAnyIP(8010));
this.app = builder.Build();
this.app.MapGet("/", () => "Hello World!");
await this.app.StartAsync();
Console.WriteLine("Started.");
}
public async Task StopAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Stopping...");
await this.app.StopAsync();
Console.WriteLine("Stopped.");
}
}
Here's the content of the Systemd service unit configuration file:
[Unit]
Description=WebApp
[Service]
Type=notify
ExecStart=dotnet WebApplication1.dll
WorkingDirectory=/home/myuser/webapp
KillSignal=SIGINT
User=myuser
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
Any ideas?
Edit: As suggested, I tried the following for Program.Main()
as well ( Application
class unchanged):
using var host = Host
.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Application>();
})
.UseSystemd()
.Build();
host.Start();
host.WaitForShutdown();
The behavior is the same as before.
You have here a long explanation of the host shutdown lifecycle: https://github.com/do.net/runtime/blob/main/src/libraries/Microsoft.Extensions.Hosting/docs/HostShutdown.md . When u do systemctl stop
it calls Environment.Exit
and Environment.Exit != CTRL+C
. Add to your code host.WaitForShutdown();
You have here a short general example that might help u.
using Microsoft.Extensions.Hosting;
......
using (IHost host = builder.Build())
{
host.Services.GetRequiredService<OtherService>();
host.Start();
host.WaitForShutdown();
Console.WriteLine("Ran cleanup code inside using host block.");
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.