Консольное приложение .Net Core в Linux не будет работать как служба - PullRequest
0 голосов
/ 03 июля 2018

У меня есть постоянно работающее консольное приложение .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

Я не знаю, имеет ли это какое-либо отношение к ситуации, но я заметил разницу в столбце STAT со списком ps aux для приложения в зависимости от того, работает ли оно автономно или как служба (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  

Любые предложения будут оценены.

1 Ответ

0 голосов
/ 05 июля 2018

Я наконец понял, что происходит. Первоначальная структура метода Main в Program.cs была следующей. Этот код прекрасно работал при работе в 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();
    }
...