Linux上的.Net Core控制台应用程序将无法作为服务运行

时间:2018-07-03 05:08:29

标签: linux .net-core quartz.net systemd

我有一个持续运行的.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 vs 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  

任何建议将不胜感激。

1 个答案:

答案 0 :(得分:0)

我终于发现这是怎么回事。 Program.cs中Main方法的原始结构如下。当在Windows和Linux上作为与终端会话相关联的独立进程运行时,此代码可以正常工作。在Linux上,一旦终止终端会话,后台程序将终止,因为主程序线程也将终止。

当程序作为Linux服务运行时,没有与该程序关联的终端会话,因此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();
    }