我有一个连续运行的 .Net Core (2.1) 控制台应用程序,它使用 Quartz.Net 调度程序来安排许多重复的后台任务。我正在尝试在 Linux 服务器 (16.04) 上运行该应用程序。该应用程序作为独立应用程序运行时运行良好。但是,当我尝试将该应用程序作为 systemd 服务运行时,它会挂起。该应用程序加载并调度 Quartz.Net 中的各种任务,但调度的后台任务永远不会执行。服务执行与独立执行有何不同?
systemd服务配置文件如下:
[Unit]
Description=FiddleMon.Background
[Service]
User=ubuntu
Restart=on-failure
ExecStart=/home/ubuntu/scripts/start-fiddlemon.background.sh
[Install]
WantedBy=multi-user.target
我不知道这是否与这种情况有关,但我确实注意到应用程序的 ps aux
列表中的 STAT 列有所不同,具体取决于它是否独立运行或作为服务(SLl 与 SLl+):
standalone => 1782 1.4 8.4 2923228 171996 pts/1 SLl+ 00:18 0:33 /usr/bin/dotnet FiddleMon.Background.dll
service => 1518 8.9 4.7 2767936 97132 ? SLl 23:59 0:03 /usr/bin/dotnet FiddleMon.Background.dll
如有任何建议,我们将不胜感激。
最佳答案
我终于明白是怎么回事了。 Program.cs 中 Main 方法的原始结构如下所示。此代码在 Windows 和 Linux 上作为与终端 session 关联的独立进程运行时运行良好。在 Linux 上,只要终端 session 终止,后台程序就会终止,因为主程序线程也会终止。
当程序作为 Linux 服务运行时,没有与程序关联的终端 session ,因此 Console.ReadLine()
不会导致线程阻塞,程序会立即终止。解决方案是将 Console.ReadLine()
替换为一些会导致线程阻塞并保持事件状态的代码,以便由 Quartz.Net 管理的后台线程可以执行。有很多不同的方法可以实现这一点,并且有许多关于“最佳”方法的 StackOverflow 讨论。我的简单解决方案是将 Console.ReadLine
替换为 Thread.Sleep(Timeout.Infinite)
。这会导致主线程阻塞并永远保持事件状态。请注意,使用此解决方案,如果您希望能够手动终止程序,则需要有一种方法可以在主线程之外执行此操作,因为它永远处于休眠状态。
**Original Code**
static void Main(string[] args)
{
_scheduler = InitializeQuartzScheduler();
_scheduler.ScheduleBackgroundJob<BackgroundJob1>(Yesterday.At(1, 30).AsPstToUtc(), 1.Hours());
_scheduler.ScheduleBackgroundJob<BackgroundJob2>(Yesterday.At(0, 10, 30).AsPstToUtc(), 10.Minutes());
...
_scheduler.ScheduleBackgroundJob<BackgroundJob7>(Yesterday.At(1, 45).AsPstToUtc(), 8.Hours());
_scheduler.ScheduleBackgroundJob<BackgroundJob8>(Yesterday.At(0, 10).AsPstToUtc(), 6.Hours());
Console.Readline();
}
关于linux - Linux 上的 .Net Core 控制台应用程序不会作为服务运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51147020/