问题描述
我可以编写一个可以长时间运行的CLI应用程序并运行它,但是我假设它不能满足人们对符合标准的linux守护程序的所有期望(响应SIGTERM,由System V开头)初始化过程,忽略终端I/O信号,等.)
I could just write a long-running CLI app and run it, but I'm assuming it wouldn't comply to all the expectations one would have of a standards-compliant linux daemon (responding to SIGTERM, Started by System V init process, Ignore terminal I/O signals, etc.)
大多数生态系统都有一些最佳实践方法,例如,在python中,您可以使用 https://pypi.python.org/pypi/python-daemon/
Most ecosystems have some best-practice way of doing this, for example, in python, you can use https://pypi.python.org/pypi/python-daemon/
是否有一些有关如何使用.Net Core进行操作的文档?
Is there some documentation about how to do this with .Net Core?
推荐答案
我的想法与.net核心Web主机如何等待控制台应用程序中的关闭类似.我在GitHub上进行了审查,并能够提取出他们如何执行Run
I toyed with an idea similar to how .net core web host waits for shutdown in console applications. I was reviewing it on GitHub and was able to extract the gist of how they performed the Run
public static class ConsoleHost {
/// <summary>
/// Block the calling thread until shutdown is triggered via Ctrl+C or SIGTERM.
/// </summary>
public static void WaitForShutdown() {
WaitForShutdownAsync().GetAwaiter().GetResult();
}
/// <summary>
/// Runs an application and block the calling thread until host shutdown.
/// </summary>
/// <param name="host">The <see cref="IWebHost"/> to run.</param>
public static void Wait() {
WaitAsync().GetAwaiter().GetResult();
}
/// <summary>
/// Runs an application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <param name="host">The <see cref="IConsoleHost"/> to run.</param>
/// <param name="token">The token to trigger shutdown.</param>
public static async Task WaitAsync(CancellationToken token = default(CancellationToken)) {
//Wait for the token shutdown if it can be cancelled
if (token.CanBeCanceled) {
await WaitAsync(token, shutdownMessage: null);
return;
}
//If token cannot be cancelled, attach Ctrl+C and SIGTERN shutdown
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource()) {
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: "Application is shutting down...");
await WaitAsync(cts.Token, "Application running. Press Ctrl+C to shut down.");
done.Set();
}
}
/// <summary>
/// Returns a Task that completes when shutdown is triggered via the given token, Ctrl+C or SIGTERM.
/// </summary>
/// <param name="token">The token to trigger shutdown.</param>
public static async Task WaitForShutdownAsync(CancellationToken token = default (CancellationToken)) {
var done = new ManualResetEventSlim(false);
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(token)) {
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: string.Empty);
await WaitForTokenShutdownAsync(cts.Token);
done.Set();
}
}
private static async Task WaitAsync(CancellationToken token, string shutdownMessage) {
if (!string.IsNullOrEmpty(shutdownMessage)) {
Console.WriteLine(shutdownMessage);
}
await WaitForTokenShutdownAsync(token);
}
private static void AttachCtrlcSigtermShutdown(CancellationTokenSource cts, ManualResetEventSlim resetEvent, string shutdownMessage) {
Action ShutDown = () => {
if (!cts.IsCancellationRequested) {
if (!string.IsNullOrWhiteSpace(shutdownMessage)) {
Console.WriteLine(shutdownMessage);
}
try {
cts.Cancel();
} catch (ObjectDisposedException) { }
}
//Wait on the given reset event
resetEvent.Wait();
};
AppDomain.CurrentDomain.ProcessExit += delegate { ShutDown(); };
Console.CancelKeyPress += (sender, eventArgs) => {
ShutDown();
//Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
}
private static async Task WaitForTokenShutdownAsync(CancellationToken token) {
var waitForStop = new TaskCompletionSource<object>();
token.Register(obj => {
var tcs = (TaskCompletionSource<object>)obj;
tcs.TrySetResult(null);
}, waitForStop);
await waitForStop.Task;
}
}
我尝试改编IConsoleHost
之类的东西,但很快意识到我对它进行了过度设计.将主要部分提取到类似Console.ReadLine
I tried adapting something like a IConsoleHost
but quickly realized I was over-engineering it. Extracted the main parts into something like await ConsoleUtil.WaitForShutdownAsync();
that operated like Console.ReadLine
然后允许该实用程序像这样使用
This then allowed the utility to be used like this
public class Program {
public static async Task Main(string[] args) {
//relevant code goes here
//...
//wait for application shutdown
await ConsoleUtil.WaitForShutdownAsync();
}
}
从那里创建一个 systemd ,如下面的链接中所示,应该会为您提供其余的方法
from there creating a systemd as in the following link should get you the rest of the way
这篇关于如何使用.Net Core编写Linux守护程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!