with publicar net mac asp linux asp.net-core daemon

publicar - Cómo escribir un demonio de Linux con.Net Core



install dot net core on ubuntu (4)

Podría escribir una aplicación CLI de larga duración y ejecutarla, pero supongo que no cumplirá con todas las expectativas que uno tendría de un demonio de Linux compatible con los estándares (respondiendo a SIGTERM, iniciado por el proceso de inicio del Sistema V, Ignore las señales de E / S del terminal, etc. )

La mayoría de los ecosistemas tienen una forma mejor de hacer esto, por ejemplo, en Python, puede usar https://pypi.python.org/pypi/python-daemon/

¿Hay alguna documentación sobre cómo hacer esto con .Net Core?


¿Has probado Thread.Sleep (Timeout.Infinite) ?

using System; using System.IO; using System.Threading; namespace Daemon { class Program { static int Main(string[] args) { if (Environment.OSVersion.Platform == PlatformID.Win32NT) { Log.Critical("Windows is not supported!"); return 1; } Agent.Init(); Agent.Start(); if (Agent.Settings.DaemonMode || args.FirstOrDefault() == "daemon") { Log.Info("Daemon started."); Thread.Sleep(Timeout.Infinite); } Agent.Stop(); } } }


Lo mejor que pude encontrar se basa en la respuesta a otras dos preguntas: matar con gracia a un demonio .NET Core que se ejecuta en Linux y ¿es posible esperar un evento en lugar de otro método asíncrono?

using System; using System.Runtime.Loader; using System.Threading.Tasks; namespace ConsoleApp1 { public class Program { private static TaskCompletionSource<object> taskToWait; public static void Main(string[] args) { taskToWait = new TaskCompletionSource<object>(); AssemblyLoadContext.Default.Unloading += SigTermEventHandler; Console.CancelKeyPress += new ConsoleCancelEventHandler(CancelHandler); //eventSource.Subscribe(eventSink) or something... taskToWait.Task.Wait(); AssemblyLoadContext.Default.Unloading -= SigTermEventHandler; Console.CancelKeyPress -= new ConsoleCancelEventHandler(CancelHandler); } private static void SigTermEventHandler(AssemblyLoadContext obj) { System.Console.WriteLine("Unloading..."); taskToWait.TrySetResult(null); } private static void CancelHandler(object sender, ConsoleCancelEventArgs e) { System.Console.WriteLine("Exiting..."); taskToWait.TrySetResult(null); } } }


Si está intentando encontrar algo más sólido, encontré una implementación en Github que parece prometedora: .NET Core Application bloquea la comunicación basada en mensajes . Utiliza HostBuilder Host , HostBuilder , ApplicationServices , ApplicationEnvironment , etc para implementar un servicio de mensajería.

No parece que esté listo para la reutilización de la caja negra, pero parece que podría ser un buen punto de partida.

var host = new HostBuilder() .ConfigureServices(services => { var settings = new RabbitMQSettings { ServerName = "192.168.80.129", UserName = "admin", Password = "Pass@word1" }; }) .Build(); Console.WriteLine("Starting..."); await host.StartAsync(); var messenger = host.Services.GetRequiredService<IRabbitMQMessenger>(); Console.WriteLine("Running. Type text and press ENTER to send a message."); Console.CancelKeyPress += async (sender, e) => { Console.WriteLine("Shutting down..."); await host.StopAsync(new CancellationTokenSource(3000).Token); Environment.Exit(0); }; ...


Jugué con una idea similar a la de cómo el host web .net core espera el apagado en las aplicaciones de la consola. Lo estaba revisando en GitHub y pude extraer la esencia de cómo se realizó la Run

https://github.com/aspnet/Hosting/blob/15008b0b7fcb54235a9de3ab844c066aaf42ea44/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs#L86

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; } }

Intenté adaptar algo como un IConsoleHost pero rápidamente me di cuenta de que estaba sobre- IConsoleHost . Extrajo las partes principales en algo como await ConsoleUtil.WaitForShutdownAsync(); que operaba como Console.ReadLine

Esto permitió que la utilidad se utilizara de esta manera.

public class Program { public static async Task Main(string[] args) { //relevant code goes here //... //wait for application shutdown await ConsoleUtil.WaitForShutdownAsync(); } }

a partir de ahí, la creación de un systemd como en el siguiente enlace le dará el resto del camino

developers.redhat.com/blog/2017/06/07/…