优雅地停止在Linux上运行的.NET Core守护进程

46

我创建了一个在 Ubuntu 14.04 机器上作为守护进程运行的 .NET Core 控制台应用程序。

我想停止服务,而不是强制停止,并能够处理 kill 事件。

我该如何实现这一点?


5
愿意分享你的代码吗?将一个.NET Core控制台应用程序转换为Ubuntu守护进程的步骤是什么? - lasseschou
3
我所做的唯一事情就是从GitHub复制了一个默认的初始化脚本;启动函数调用dotnet library.dll,停止函数则是:kill dotnet library.dll - user4388177
在Linux中,您是否在shell脚本内运行dotnet,例如,shell脚本调用dotnet app.dll。对我们来说,这引起了问题。为了缓解这个问题,我们添加了exec dotnet app.dll,这有助于将SIGTERM信号传播到dotnet应用程序,而不是让shell脚本直接处理SIGTERM。 - AAATechGuy
2个回答

59

自@Stefano的回答一年以来,.NET Core已经大大发展。在.NET Core 2.0中,您现在可以使用众所周知的AppDomain.CurrentDomain.ProcessExit事件,而不是AssemblyLoadContext.Default.Unloading。它适用于Linux上的控制台应用程序,在Docker中也能正常工作。


1
我制作了一个简单的示例,展示如何处理此事件:https://github.com/rquackenbush/DotNetSigTermTest - RQDQ
5
AppDomain.CurrentDomain.ProcessExit 方法只允许清理工作进行 2 秒钟,且无法使用托管代码覆盖此行为。 - Parag
1
@Parag 我认为你误读了文档,或者它已经被更改了。这个时间限制只存在于 .NET Framework 中,而不是 .NET Core。https://learn.microsoft.com/en-us/dotnet/api/system.appdomain.processexit?view=netframework-4.8 - Anders Emil
@AndersEmil 我确定它适用于 .net core。请检查您发送的文档链接中的“适用于”部分。 - Parag
5
这篇文章讲的是ProcessExit事件,而不是时间限制。在紫色的提示框中明确说明,在.NET Core中不存在时间限制,我很惊讶你没有注意到它。 - Anders Emil
1
@AndersEmil 我重新阅读了一遍,你是正确的。对于错误信息我很抱歉。 - Parag

29
您想要发送 SIGTERM 信号给正在运行的进程:
kill <PID>

而且这个过程应该正确处理关闭。

不幸的是,.NET Core 的文档不够完善,但它有能力处理 Unix 信号(与Mono的方式不同)。GitHub问题

如果你使用的是带有UpstartUbuntu,你需要一个初始化脚本,在停止请求时发送kill信号:示例初始化脚本

project.json中添加依赖项:

"System.Runtime.Loader": "4.0.0"

这将为您提供AssemblyLoadContext

然后,您可以处理SIGTERM事件:

AssemblyLoadContext.Default.Unloading += MethodInvokedOnSigTerm;

注意:

使用Mono时,正确的处理方式是通过UnixSignal: Mono.Unix.Native.Signum.SIGTERM

编辑:

正如@Marc在他最近的回答中指出的那样,这不再是实现此目的的最佳方式。从.NET Core 2.0开始,支持使用AppDomain.CurrentDomain.ProcessExit事件。


你正在使用哪个版本的.NET Core?你是否在某个时候修改了加载上下文? - Stefano d'Antonio
版本:1.0.0-preview2-003121... 我还注意到,当我运行“dotnet run”时,它会启动两个进程。我认为这就是它无法正常工作的原因,因为它只杀死了其中一个进程而不是两个。 - dcinadr
2
尝试进入已发布的 DLL 文件夹并使用以下命令运行:dotnet <DllName>.dll(不要加run),这将只运行一个进程,您可以尝试杀死该进程。 - Stefano d'Antonio
谢谢。是的,这与我让它工作的方式类似。唯一的区别是我使用了“dotnet exec <DllName>.dll”。 - dcinadr
我之前不知道exec,所以我快速搜索了一下,找到了这个链接:https://github.com/dotnet/cli/issues/2243 但是我猜测它的行为与dotnet <dll>类似。 - Stefano d'Antonio
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接