컴퓨터/운영체제(주로 리눅스)

[리눅스] systemd 개념과 systemd를 통해서 service 실행하는 방법

REAKWON 2022. 6. 27. 17:37

systemd 뿐만 아니라 데몬의 특징을 담은 더 많은 정보와 예제를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

 

systemd

systemd에서 끝 d는 daemon을 의미합니다. deamon은 background에서 실행이 되는  프로세스입니다. 그러한 deamon을 실행하고 관리하게 해주는 daemon이 바로 systemd입니다. systemd는 부팅하고나서 가장 먼저 실행되는 데몬입니다. 

이전에는 init이라는 데몬이 있었는데 이를 대체하고 init보다 기능이 추가되어서 나온 것이 systemd입니다. 그래서 이전의 init과 같이 PID가 1이 됩니다. 부모프로세스가 없으므로 PPID 또한 1이 됩니다. 

systemd는 리소스를 unit이라고 불리는 단위로 관리합니다. 어떤 type의 unit이 있을까요? 아래의 표로 정리하였습니다. 

.service .socket .device .mount .automount .swap .target .path .timer
.snapshot .slice .scope            

 

 - 여기서는 .service만 설명합니다. 가장 많이 쓰니까요~ .service에서는 service나 application을 서버상에서 어떻게 관리할지를 명세합니다. service의 시작, 중지, 그리고 어떠한 상황에서 자동적으로 실행하는지, 어떠한 종속성을 가지고 있는지에 대한 정보를 갖고 있습니다.

만약 .service를 추가하려면 /etc/systemd/system 디렉토리에 끝 확장자로 .유닛타입 식으로 써주면 됩니다. service의 경우에는 끝 확장자가 .service가 됩니다. 그리고 시스템은 일반적으로 unit file들을 /lib/systemd/system 하위에 복사하여 유지합니다. 여기서 아주 간단한 service를 등록하고 실행하는 방법을 알아보도록 하겠습니다. 

 

1. 실행 파일 생성

사용할 실행 파일(myservice.c)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

int main(){
        int fd;
        char buf[64] = "myservice start!\n";

        fd = open("/tmp/log.txt",O_CREAT|O_WRONLY|O_TRUNC,0644);
        //열기 실패시
        if(fd<0) return -1;

        write(fd, buf, strlen(buf));

        while(1){
                //계속 running되게 하기 위해 무한 loop
                sleep(1);
        }
        close(fd);
        return 0;

}

위 소스코드로 컴파일하여 아래의 실행 파일로 만들어보도록 하겠습니다. 권한 문제가 생길까봐 777을 부여했습니다.

# gcc myservice.c -o myservice
# chmod 777 myservice

 

2. Unit 파일 생성

우리는 service를 생성할 것이기 때문에 /etc/systemd/system 하위에 myservice.service 파일을 생성하도록 하겠습니다. 

[Unit]
Description=test service

[Service]
ExecStart=/home/ubuntu/systemd/myservice

[Install]
WantedBy=multi-user.target

 

2.1 Unit Section

보통 가장 처음 등작하는 Section입니다. 여기서는 유닛에 대한 meta data와 다른 유닛간의 관계를 설정하는 곳입니다. 

Description : 이 Unit에 대한 설명을 뜻합니다. 짧고, 간략하지만 핵심 정보를 담고 있도록 설명하는 곳입니다.

Documentation : 이 서비스에 대한 문서가 있는 URI를 제공합니다. man 페이지나 웹 사이트가 될 수 있습니다. 이런 정보들은 systemctl status 명령어에서 노출됩니다.

After : 이 Unit보다 먼저 실행되어야할 Unit들을 나열합니다.

Before : 이 Unit보다 늦게 실행되어야할 Unit들을 나열합니다. 

Requires : 이 Unit이 의존하는 모든 Unit을 나열합니다. 여기서 나열된 Unit들은 전부 성공적으로 실행이 되고 있어야합니다.

Wants : Requires와 유사합니다만, Requires보다는 그렇게 엄격하지 않습니다. 다른 Unit이 실패하더라도 지금 Unit을 실행합니다.

BindsTo : Requires와 유사합니다. 대신 연관된 유닛이 종료되면 같이 service가 종료됩니다.

 

2.2 Service Section 

Service Section은 서비스에만 적용할 수 있는 특징을 정의합니다. Unit에는 여러 종류가 있다고 위에서 표로 정의해놓았죠? mount도 있고, swap도 있고... 그중 Service에만 적용하는 구성입니다.

Type : service가 어떤 형태로 동작이 되는지를 설정합니다. systemd에게 이 service가 어떻게 관리되고 상태를 탐지하는지 알려주는 지시자입니다. 아래 중 하나로 동작이 됩니다. 

  ● simple : 명시하지 않을 경우 simple로 동작합니다. ExecStart는 설정이 되어 있어야합니다. 

  ● forking : service가 자식 프로세스를 생성할때 사용합니다. 이때 자식을 생성한 프로세스는 곧 장 나갈때 사용됩니다.

  ● oneshot : 프로세스가 오래 실행되지 않을때 systemd가 이 service가 종료되기를 기다려야할때 이 값을 사용할 수 있습  니다. service가 종료된 후 systemd가 진행을 계속하게 됩니다.

  ● dbus : 지정된 Bus Name이 D-Bus에 준비될때까지 기다리고, D-Bus가 준비되면 service가 실행됩니다.

  ● notify : service가 startup이 끝날때 notification(signal)을 발생시킵니다. 이런 상황이 발생할때 systemd는 다음 unit으로 넘어갑니다. 

  ● idle :  모든 작업이 실행될때까지 서비스가 실행이 되지 않습니다. 즉, 모든 작업이 실행되어서야 실행됩니다.

ExecStart : 실행할 command의 절대경로를 지정합니다.  

ExecStartPre : 서비스가 실행하기 전의 command를 지정합니다. 서비스 시작전 명령어를 실행합니다.

ExecStartPost : 서비스를 시작하고 나서의 command를 지정합니다. 서비서 시작 후에 명령어를 실행하기 됩니다.

ExecStop : 서비스가 stop될때 실행되어야할 command를 정합니다. 

Restart : systemd가 자동으로 재시작하려고 시도하는 상황을 정의합니다. alway, on-success, on-failure, on-abnormal, on-abort, on-watchdog를 사용할 수 있습니다. 

TimeoutSec : systemd가 service가 실행할때까지 기다리는 시간을 의미합니다. service를 stop할때까지 기다리는 시간이라고도 말할 수 있겠네요.

FailureAction : service 실패시 어떤 동작할 할지를 정의합니다. none, reboot, reboot-force, reboot-immediate, poweroff, poweroff-force, poweroff-immediate, exit, exit-force 중 하나를 사용합니다.

User : service가 실행될때 어떠한 권한으로 실행이 되는지를 설정합니다. user 이름이 될 수 있고, user id로 설정할 수도 있습니다. 그러나 user 이름이 알아보기 좋겠죠? 

Group : User와 마찬가지로 service가 실행될때 가지는 그룹 권한을 설정합니다. 

 

2.3 Install Section

보통 파일의 마지막에 존재합니다. 이 Section은 optional입니다. Unit이 enable하거나 disable 될때 Unit의 행동을 정의합니다.

WantedBy : 어떻게 Unit이 활성화(enable)되는지 명세합니다. 

Also : service가 enable, disable될때 집합 단위로 같이 enable, disable할 serivce들을 의미합니다.

Alias : 이 service의 별칭을 줍니다. 

 

3. service 실행, 상태, 종료

service 실행 : service를 실행하는 명령어는 아래와 같습니다. 서비스가 새로 추가됐으니, daemon을 다시 load하는 과정도 있어야합니다.

# systemctl daemon-reload
# systemctl start myservice

 

자, 실행이 되었다면 /tmp 하위에 log.txt라는 파일이 생겨나고 파일 내용이 적혀져 있어야합니다. 확인해볼까요? 

# cat /tmp/log.txt
myservice start!

 

위처럼 파일이 생겼으며 내용도 채워져있음을 확인했습니다. 그리고 현재 데몬이 실행되고 있는지 확인해봅시다. 

# ps -ef | grep myservice
root       42450       1  0 19:51 ?        00:00:00 /home/ubuntu/systemd/myservice

 

위와 같이 PID가 42450인 프로세스가 있는 것을 확인했습니다. 부모 PID는 1입니다. 시스템 데몬이라는 것을 알 수 있죠?

 

service 상태 확인 : service의 상태가 어떤지 보고 싶다면 status를 옵션으로 주면 됩니다. 4번째줄에 active로 실행중인 상태를 확인할 수 있습니다.

# systemctl status myservice
● myservice.service - test service
     Loaded: loaded (/etc/systemd/system/myservice.service; static; vendor preset: enabled)
     Active: active (running) since Mon 2022-06-27 19:45:00 KST; 51s ago
   Main PID: 42434 (myservice)
      Tasks: 1 (limit: 2295)
     Memory: 140.0K
     CGroup: /system.slice/myservice.service
             └─42434 /home/ubuntu/systemd/myservice

 6월 27 19:45:00 ubuntu-VirtualBox systemd[1]: Started test service.

 

service 종료 : service를 종료하고 싶다면 stop을 옵션으로 주면 됩니다.

# systemctl stop myservice
# systemctl status myservice
● myservice.service - test service
     Loaded: loaded (/etc/systemd/system/myservice.service; static; vendor preset: enabled)
     Active: inactive (dead)

 

service 재시작 : stop과 start를 하면 재시작이 되죠. 한번에 할 수도 있습니다.

# systemctl restart myservice

 

service 부팅시 시작, 해제 : 이 서비스를 부팅시에 자동으로 실행하게 만들 수 있습니다. 단, Install Section을 정의해놔야합니다. 반대로 부팅시 시작 해제하려면 disable을 사용하면 됩니다. 

# systemctl enable myservice
# systemctl disable myservice

 

기본적으로 systemd에 service를 등록하고 실행하는 방법을 알아보았습니다. 이 밖에도 훨씬 많은 내용이 존재하여 이 포스팅에 전부 담아낼 수가 없습니다. 그래서 아래의 페이지에서 필요할때 찾아서 적용하시면 되겠습니다.

https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files#install-section-directives

 

 

Understanding Systemd Units and Unit Files | DigitalOcean

 

www.digitalocean.com

 

https://www.freedesktop.org/software/systemd/man/systemd.directives.html

 

systemd.directives

Name systemd.directives — Index of configuration directives Unit directives Directives for configuring units, used in unit files....

www.freedesktop.org

 

반응형