Как запустить приложение dotnet в фоновом режиме с помощью sudo в Linux?

У меня возникли странные проблемы, которые я не знаю, как решить. Я использую CodeDeploy для развертывания своих приложений в экземпляре AWS EC2, и там мне нужно указать сценарий для выполнения процессов в моих экземплярах, один из которых является приложением .NET Core.

Я публикую свое приложение с помощью dotnet publish в Windows и копирую необходимые библиотеки DLL в экземпляр EC2 Linux.

Я могу нормально запустить приложение, и оно ведет себя так, как ожидалось.

sudo dotnet application.dll

Однако это просто до тех пор, пока я не завершу приложение и не буду работать в фоновом режиме.

Проблема возникает, когда я пытаюсь запустить свое приложение в фоновом режиме, чтобы продолжить работу с другими приложениями или выполнять другие задачи.

Я обычно использую screen или nohup для запуска приложений в фоновом режиме, но, похоже, это не работает для этого приложения. Скрин в скрипте не работает, а nohup запускает приложение, но выдает ошибку

Для запуска с помощью nohup я использую sudo nohup dotnet application.dll &, и я получаю сообщение об ошибке в журнале

Unhandled Exception: System.UnauthorizedAccessException: Access to the path is denied. ---> System.IO.IOException: Bad file descriptor
   --- End of inner exception stack trace ---
   at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirectory, Func`2 errorRewriter)
   at Interop.CheckIo(Int64 result, String path, Boolean isDirectory, Func`2 errorRewriter)
   at System.ConsolePal.Read(SafeFileHandle fd, Byte[] buffer, Int32 offset, Int32 count)
   at System.ConsolePal.UnixConsoleStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.StreamReader.ReadBuffer()
   at System.IO.StreamReader.ReadLine()
   at System.IO.SyncTextReader.ReadLine()
   at System.Console.ReadLine()
   at Application.Program.Main(String[] args) in F:\Applications\Server\Program.cs:line 38

Теперь я понимаю, почему это выбрасывается, поскольку путь в ошибке — это путь к моему проекту в Windows, но почему это происходит только при использовании nohup? Это отлично работает, если я запускаю его на переднем плане и не выдает ошибку.

Как я могу запустить это приложение в фоновом режиме без использования экрана?


ИЗМЕНИТЬ

Сначала я подумал, что это какая-то проблема совместимости, поскольку она была создана для Windows, однако это не так. Я переместил проект в экземпляр Linux и повторно опубликовал его там, и я все еще получаю ту же ошибку при запуске sudo nohup dotnet application.dll &

 Unhandled Exception: System.UnauthorizedAccessException: Access to the path is denied. ---> System.IO.IOException: Bad file descriptor
   --- End of inner exception stack trace ---
   at Interop.ThrowExceptionForIoErrno(ErrorInfo errorInfo, String path, Boolean isDirectory, Func`2 errorRewriter)
   at Interop.CheckIo(Int64 result, String path, Boolean isDirectory, Func`2 errorRewriter)
   at System.ConsolePal.Read(SafeFileHandle fd, Byte[] buffer, Int32 offset, Int32 count)
   at System.ConsolePal.UnixConsoleStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.StreamReader.ReadBuffer()
   at System.IO.StreamReader.ReadLine()
   at System.IO.SyncTextReader.ReadLine()
   at System.Console.ReadLine()
   at Application.Program.Main(String[] args) in /opt/servers/Server/Program.cs:line 38

я только что попробовал

sudo dotnet application.dll > out.log 2>&1 &

который, кажется, запускает программу без ошибок, однако всякий раз, когда выполняется другая команда, фоновое приложение отправляется в состояние STOPPED и не продолжает работать.

[1]+ Stopped sudo dotnet application.dll > out.log 2>&1

ubuntu@:/opt/servers/Server$ sudo dotnet application.dll > out.log  2>&1 &
[1] 2448
ubuntu@:/opt/servers/Server$ netstat -tulpn
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp6       0      0 :::22                   :::*                    LISTEN      -
udp   214656      0 0.0.0.0:1000            0.0.0.0:*                           -
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -

[1]+  Stopped                 sudo dotnet application.dll > out.log 2>&1

Следующим шагом будет изучение использования screen в автономном режиме.

screen -d -m bash -c 'cd /opt/server && sudo dotnet application.dll &'

Эта команда в настоящее время не создает экранное окно...

ИЗМЕНИТЬ

Мне пришлось удалить & в конце, и теперь он работает как положено.

screen -d -m -S SERVER bash -c 'cd /opt/server && sudo dotnet application.dll'


person jjmcc    schedule 25.03.2018    source источник


Ответы (3)


Если он в Windows (я не был уверен, нужен он вам там или нет), просто запустите start, и он по существу запустится асинхронно. Пример (передний и задний план)

запустить dotnet yourdll.dll

start /b dotnet yourdll.dll

В Linux

nohup ./yourSelfContainedapp > /dev/null 2>&1 &

Or

nohup dotnet yourapp.dll > /dev/null 2>&1 &

И ваша приведенная выше экранная команда (которую вы можете отсоединить/присоединить обратно)

person Adam Tuliper - MSFT    schedule 26.03.2018
comment
Запуск только 'nohup dotnet myapp.dll' работает сам по себе без '› /dev/null 2›&1 &' Не уверен, что это хорошая идея или нет, лол ... можете ли вы объяснить, что такое '› /dev/null 2 ›&1 &' часть делает? ---- Редактировать: неважно, только что нашел что-то, что говорит, что он по существу отбрасывает весь вывод консоли. То, что я сделал, где-то записывает вывод. - person Michael Buchok; 25.10.2018

Для меня проблема заключалась в следующем:

Console.ReadKey();

Я заменил код на:

var cancellationTokenSource = new CancellationTokenSource();
AppDomain.CurrentDomain.ProcessExit += (s, e) => cancellationTokenSource.Cancel();
Console.CancelKeyPress += (s, e) => cancellationTokenSource.Cancel();
await Task.Delay(-1, cancellationTokenSource.Token).ContinueWith(t => { });

С помощью этого кода вы можете закрыть консольное приложение с помощью CTRL+C или сигнала SIGTERM.

Надеюсь это поможет!

person Tovich    schedule 29.08.2018

Предыдущее решение не работало для меня, когда прослушиватель сообщений не получал сообщения, поэтому я заменил Console.ReadLine() на Thread.Sleep(Timeout.Infinite) в последней строке моей основной программы. Это решило проблему nohup, проблему ведения журнала и работу в фоновом режиме. Я не помню, чтобы мне приходилось делать эти вещи на Java, чтобы задержать прослушиватель сообщений Tibco или Rabbit.

person Edmond Wong    schedule 03.06.2020