Systemd 유닛 이해하기: 서비스 구성의 심층 분석
Systemd는 최신 Linux 배포판에서 서비스를 초기화하고 관리하는 사실상의 표준이 되었습니다. Systemd는 본질적으로 유닛 파일(unit files)에 의존하여 서비스, 장치, 마운트 지점 등을 포함한 다양한 시스템 리소스를 정의하고 제어합니다. 이러한 유닛 파일의 구조와 구문을 이해하는 것은 시스템 관리자와 개발자 모두에게 중요하며, 이를 통해 기존 서비스를 효과적으로 관리하고 특정 요구 사항에 맞춘 사용자 지정 서비스를 생성할 수 있습니다.
본 문서는 systemd 유닛 파일을 포괄적으로 심층 분석하며, 특히 서비스 유닛(.service 파일)에 중점을 둡니다. 우리는 유닛 파일의 기본 구조, 일반적인 지시어, 그리고 이를 읽고 수정하고 생성하는 실용적인 예제를 살펴볼 것입니다. 이 가이드를 마치면 systemd의 강력한 기능을 활용하여 시스템 서비스를 자신 있게 관리할 수 있는 확고한 기반을 갖추게 될 것입니다.
Systemd 유닛 파일이란 무엇인가요?
Systemd 유닛 파일은 특정 유닛에 대한 구성 지시어를 담고 있는 간단한 텍스트 파일입니다. 유닛은 systemd에 의해 관리되는 리소스를 나타냅니다. 가장 일반적인 유형은 서비스 유닛(service unit)으로, 백그라운드 프로세스 또는 애플리케이션을 시작, 중지, 재시작 및 관리하는 방법을 정의합니다.
유닛 파일은 섹션으로 구성되며, 각 섹션은 대괄호([])로 표시됩니다. 서비스 유닛에 가장 중요한 섹션은 다음과 같습니다.
[Unit]: 유닛에 대한 메타데이터, 종속성, 순서를 포함합니다.[Service]: 서비스를 실행하는 방법을 포함하여 서비스 자체의 동작을 정의합니다.[Install]: 유닛을 활성화하거나 비활성화하는 방법을 지정하며, 일반적으로 대상 유닛(target units)에 연결합니다.
Systemd는 여러 표준 디렉터리에서 유닛 파일을 찾으며, 가장 일반적인 경로는 다음과 같습니다.
/etc/systemd/system/: 로컬로 구성된 유닛용으로, 기본 설정을 재정의합니다./usr/lib/systemd/system/: 패키지에 의해 설치된 유닛용입니다.
.service 유닛 파일의 해부
일반적인 .service 유닛 파일을 구성 요소별로 자세히 살펴보겠습니다.
[Unit] 섹션
이 섹션은 설명 정보를 제공하고 유닛 간의 관계를 정의합니다.
Description=: 서비스에 대한 사람이 읽을 수 있는 설명입니다.Documentation=: 서비스 문서로 연결되는 URL 또는 경로입니다.After=: 나열된 유닛이 시작을 마친 후 이 유닛이 시작되어야 함을 지정합니다.Requires=:After=와 유사하지만, 나열된 유닛을 필수 사항으로 만듭니다. 필수 유닛이 시작에 실패하면 이 유닛도 실패합니다.Wants=: 종속성의 약한 형태입니다. 이 유닛은 원하는 유닛을 시작하려고 시도하지만, 해당 유닛의 실패가 이 유닛의 시작을 막지는 않습니다.Conflicts=: 이 유닛과 동시에 실행될 수 없는 유닛을 지정합니다.
[Unit] 섹션 예시:
[Unit]
Description=My Custom Web Server
Documentation=https://example.com/docs/my-web-server
After=network.target
이는 네트워크를 사용할 수 있게 된 후 사용자 지정 웹 서버가 시작되어야 함을 나타냅니다.
[Service] 섹션
이 섹션은 서비스를 실행하기 위한 핵심 로직이 위치하는 곳입니다.
Type=: 프로세스 시작 유형을 정의합니다. 일반적인 유형은 다음과 같습니다.simple(기본값): 메인 프로세스는ExecStart=에 의해 시작되는 프로세스입니다. systemd는ExecStart=프로세스가 포크된 직후 서비스가 시작된 것으로 간주합니다.forking: 자식 프로세스를 포크하고 종료하는 전통적인 데몬에 사용됩니다. systemd는 부모 프로세스가 종료되기를 기다립니다.oneshot: 단일 명령을 실행한 후 종료되는 작업용입니다.notify: 서비스가 시작을 완료했을 때 systemd에 알림을 보냅니다.dbus: D-Bus 이름을 획득하는 서비스용입니다.
ExecStart=: 서비스를 시작하기 위해 실행할 명령입니다.ExecStop=: 서비스를 중지하기 위해 실행할 명령입니다.ExecReload=: 서비스를 재시작하지 않고 구성만 다시 로드하기 위해 실행할 명령입니다.Restart=: 서비스가 언제 재시작되어야 하는지 정의합니다. 옵션에는no(기본값),on-success,on-failure,on-abnormal,on-watchdog,on-abort,always가 있습니다.RestartSec=: 서비스를 재시작하기 전에 대기할 시간입니다.User=/Group=: 서비스가 실행되어야 하는 사용자 및 그룹입니다.WorkingDirectory=: 실행된 프로세스의 작업 디렉터리입니다.Environment=/EnvironmentFile=: 서비스에 대한 환경 변수를 설정합니다.
[Service] 섹션 예시:
[Service]
Type=simple
ExecStart=/usr/local/bin/my-web-server --config /etc/my-web-server.conf
User=www-data
Group=www-data
Restart=on-failure
RestartSec=5
이 구성은 웹 서버를 시작하고, www-data 사용자 및 그룹으로 실행하며, 실패할 경우 5초 지연 후 자동으로 재시작합니다.
[Install] 섹션
이 섹션은 유닛을 활성화하거나 비활성화할 때 사용됩니다. 이 섹션은 유닛이 systemd의 대상 유닛과 통합되는 방식을 정의합니다.
WantedBy=: 유닛이 활성화될 때 이 유닛을 '원해야' 하는 대상(들)을 지정합니다. 부팅 시 시작해야 하는 서비스의 경우multi-user.target이 일반적으로 사용됩니다.
[Install] 섹션 예시:
[Install]
WantedBy=multi-user.target
systemctl enable my-custom-service.service 명령을 실행하면, systemd는 /etc/systemd/system/multi-user.target.wants/에서 서비스 파일로의 심볼릭 링크를 생성하여 시스템이 다중 사용자 런레벨에 도달했을 때 서비스가 시작되도록 보장합니다.
사용자 지정 서비스 유닛 생성 및 관리
사용자 지정 서비스 유닛을 생성하는 과정을 단계별로 살펴보겠습니다.
1단계: 유닛 파일 생성
/etc/systemd/system/에 .service 확장자를 가진 새 파일을 생성합니다. 예시에서는 /etc/systemd/system/my-app.service를 생성해 보겠습니다.
[Unit]
Description=My Custom Application Service
After=network.target
[Service]
Type=simple
ExecStart=/opt/my-app/bin/run-app --port 8080
User=appuser
Group=appgroup
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
중요 고려 사항:
ExecStart명령이 액세스 가능하고 실행 권한이 있는 실행 가능한 스크립트 또는 바이너리를 가리키는지 확인하십시오.- 지정된
User와Group이 존재하지 않는 경우 생성하십시오 (sudo useradd -r -s /bin/false appuser,sudo groupadd appgroup,sudo usermod -a -G appgroup appuser). - 애플리케이션이 지정된 명령을 사용하여 올바르게 시작 및 중지될 수 있는지 확인하십시오.
2단계: Systemd 구성 다시 로드
유닛 파일을 생성하거나 수정한 후에는 systemd에게 구성을 다시 로드하도록 알려야 합니다.
sudo systemctl daemon-reload
이 명령은 새로 생성되거나 변경된 유닛 파일을 스캔하고 systemd의 내부 상태를 업데이트합니다.
3단계: 서비스 활성화 및 시작
서비스를 즉시 시작하고 부팅 시 시작하도록 구성하려면:
sudo systemctl enable my-app.service # 부팅 시작을 위한 심볼릭 링크 생성
sudo systemctl start my-app.service # 지금 서비스 시작
4단계: 서비스 관리
systemctl 명령을 사용하여 서비스를 관리합니다.
-
상태 확인:
bash sudo systemctl status my-app.service
이 명령은 서비스가 활성 상태인지 여부, 프로세스 ID, 최근 로그 항목 등을 표시합니다. -
서비스 중지:
bash sudo systemctl stop my-app.service -
서비스 재시작:
bash sudo systemctl restart my-app.service -
서비스 재로드 (
ExecReload=가 정의된 경우):
bash sudo systemctl reload my-app.service -
서비스 비활성화 (부팅 시 시작 방지):
bash sudo systemctl disable my-app.service
5단계: journalctl로 로그 보기
Systemd는 로깅을 위해 journald와 긴밀하게 통합됩니다. journalctl을 사용하여 서비스의 로그를 볼 수 있습니다.
-
특정 서비스의 로그 보기:
bash sudo journalctl -u my-app.service -
실시간으로 로그 추적:
bash sudo journalctl -f -u my-app.service -
마지막 부팅 이후의 로그 보기:
bash sudo journalctl -b -u my-app.service
모범 사례 및 팁
- 최신 애플리케이션에는
Type=notify사용: 애플리케이션이 이를 지원하는 경우,Type=notify는 systemd와의 더 나은 통합을 제공하여 서비스의 준비 상태를 정확하게 추적할 수 있도록 합니다. - 비(非) root 사용자로 서비스 실행: 보안 위험을 최소화하기 위해
[Service]섹션에서 항상User=및Group=을 지정하십시오. - 종속성 신중하게 정의:
After=,Requires=,Wants=를 사용하여 서비스가 올바른 순서로 시작되고 중요한 종속성이 충족되도록 보장하십시오. Restart=활용: 서비스 가용성을 보장하기 위해 적절한 재시작 정책을 구성하십시오.- 유닛 파일을 단순하게 유지: 복잡한 시작 시퀀스의 경우, 유닛 파일에 복잡한 명령을 직접 넣는 대신
ExecStart=로 호출되는 래퍼 스크립트를 사용하는 것을 고려하십시오. systemctl cat <unit>사용: systemd가 인식하는 유닛 파일의 전체 내용(오버라이드 포함)을 보려면 이 명령을 사용하십시오.systemctl edit <unit>사용: 이 명령은 기존 유닛에 대한 오버라이드 파일을 생성하기 위해 편집기를 엽니다. 이는 기본 유닛 파일을 직접 편집하는 것보다 더 깔끔한 수정 방법입니다.
결론
Systemd 유닛 파일, 특히 .service 파일은 최신 Linux 시스템에서 서비스 관리의 근간입니다. [Unit], [Service], [Install] 섹션으로 구성된 구조를 이해하고 systemctl 및 journalctl 명령을 숙달함으로써, 시스템 프로세스에 대한 강력한 제어 권한을 얻게 됩니다. 기존 서비스 구성을 조정하든 사용자 지정 데몬을 구축하든, 유닛 파일에 대한 확실한 이해는 시스템을 더 효율적이고 안정적이며 안전하게 관리할 수 있도록 지원합니다.