linux dotnet dll Background 구동

FGPRJS·2022년 5월 25일
0

AWS CentOS에 기본적인 linux publish한 dotnet 실행 파일(dll)을 업로드하고 기동했을 때, 터미널 종료시 종료되는 점을 발견하였다.


기본적인 백그라운드 기동

프로세스 실행 중 Ctrl+Z를 누르면 프로세스가 백그라운드로 기동된다.
그런데, 이것만으로는 터미널 종료시 기동이 되지 않는다.


nohup 명령어 사용하기

nohup으로 백그라운드 처리된 작업들은 원격 SSH 세션을 로그오프할 때 일반적으로 이들의 종료를 막기 위해 사용된다.

사용 예시 :

nohup dotnet RunThisProcessInBackground.dll &

nohup은 No Hangup의 약자로, hangup 신호 (SSH를 통한 Putty 따위의 터미널에 의존하는 프로세스들에게 로그아웃을 알리는 방식.)를 보내지 않겠다는 의미이다.

따라서 nohup을 사용하면 Putty를 끄더라도 이에 의해 실행된 프로세스들에게 종료 신호가 가지 않아 계속 구동된다.

보통 콘솔 정보로 넘어가지는 데이터들은 nohup.out 파일에 기록되게 된다.

하지만 이것으로 괜찮은 것인가?

다음 문서에서는 이를 single use를 위한 것이라 설명하고 있다.

nohup is for a single use. Think of a script that will take a long time to run but will still ultimately finish. Maybe there’s a long and complicated task that you run every now and then that takes hours to complete. You don’t want to leave a terminal open or a user logged in, so you use nohup to keep it running in the background and put all the output into whatever file you choose, whether the default nohup.out or your chosen location.

무언가 길고 오래 걸리는 단발성 작업을 하는 작업에 대해 사용한다고 기재되어 있다.

여기서 설명하는 바에 따르면, 지속적으로 운용되는 서버보다는 로그 압축기, DB 백업기 등의 주기적인 이벤트성 작업에 조금 더 적합한 것(linux의 작업 예약 스케쥴러 cron에 대해서 더 알아볼 것)으로 보인다.

출력인 nohup.out을 다음 링크를 참조하여 /dev/null로 보내버리면 데몬의 조건도 어느정도 만족하게 된다.

 nohup command >/dev/null 2>&1   # doesn't create nohup.out
  • nohup.out 출력을 /dev/null로 보내면, nohup.out은 더 이상 나오지 않는다.

하지만, 더 나아가 본격적인 데몬으로 만드는 것을 고려해 본다.


Daemon

기술적으로 엄밀히 말하자면, 유닉스에서 부모 프로세스가 PID 1(init)이고 제어하는 터미널이 없을 때 그 프로세스를 데몬이라 할 수 있다. 부모 프로세스가 종료되면 init 프로세스가 그 프로세스를 받아 들인다.

Apache 2.0+는 httpd라는 이름으로 CentOS에서 사용되고 있으며, 이는 데몬이다. (HTTP Daemon)

다음 사이트에서 .Net Core로 Daemon을 만드는 방법을 가르쳐 주고 있는데, ASP.NET에서도 이 기능을 사용함을 알 수 있다.

1. Nuget에서 Package 다운로드 하기

다음 패키지를 설치한다.

  • Microsoft.Extensions.Hosting
  • Microsoft.Extensions.Hosting.System
  • Microsoft.Extensions.Hosting.Abstractions

2. CreateHostBuilder

  • 현재 확실하지 않은 부분이 있어 기재하지 않음

3. 유닛(.service) 파일

/etc/systemd/system 폴더에는 여러가지의 .service파일들(혹은 그것을 지칭하는 링크)이 존재하는데, 이것과 같이 service파일을 만들면 systemd가 관리해준다.

# {실행할 서비스명}.service 파일

[Unit]
Description=Unity Project server daemon

[Service]
#보통 장기적으로 수행해야 하는 경우 simple이 가장 적합하다.
Type=simple
#dotnet의 경우 dotnet 경로를 앞에 붙이고
#뒤에 실행할 파일의 경로 및 파일이름을 기재해야 한다.
ExecStart=/usr/bin/dotnet /{실행할 파일 경로 포함.dll}
# ensure the service restarts after crashing
Restart=always
# amount of time to wait before restarting the service
RestartSec=5
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

이 파일을 참고하여 적절한 .service파일을 만들어준다.

이후
sudo systemctl daemon-reload 를 통해서
systemd가 추가한 서비스에 대해 이해할 수 있게 해준다. .service파일을 수정할 때 이 작업을 해야 한다. 하지 않으면 해야 한다는 메시지와 함께 작동하지 않는다.

그 이후
sudo systemctl status {실행할 service 이름}을 통해서 서비스의 상태를 확인할 수 있다.
Loaded가 뜨면 성공이다.

  • 예시 링크에서 보이는 정상 로드 예시

실패하는 몇 가지 경우에 대해 기재한다.

실패 예시)

  • Is a directory
    • .service 파일의 ExecStart 항목에서 엉뚱한 파일(디렉토리를 지정중)을 지정중이다.
  • Exec Format Error
    • dotnet 실행파일(.dll)을 읽기 위해서는 런타임의 도움이 필요하다. 런타임 경로를 기재해야 한다. 참고 문서

다음 명령으로

sudo systemctl start {실행할 서비스 이름}

Loaded된 서비스를 start하면, 서비스는 계속 실행되게 된다.

추가 참고 문서

profile
FGPRJS

0개의 댓글