Profile picture

[Linux] systemctl 이란?

JaehyoJJAng2024년 07월 03일

systemctl

systemctl은 리눅스 시스템에서 systemd 서비스 관리자의 핵심 도구이다.

systemd는 리눅스 초기화 시스템(init system)및 서비스 관리자로서, 시스템 부팅 과정을 관리하고, 시스템의 다양한 서비스(또는 데몬), 장치, 마운트 포인트 등을 통합적으로 관리한다.


과거에는 SysVinitUpstart와 같은 init 시스템이 사용되었지만, 현재 대부분의 배포판에서는 systemd를 기본으로 채택하고 있다.


주요 특징

  • 병렬 부팅(Parallel Booting): 서비스 및 유닛들을 병렬로 시작하여 부팅 시간을 단축함.
  • 소켓 기반 활성화(Socket-based Activation): 서비스가 요청될 때까지 대기하고 있다가, 요청이 오면 자동으로 시작됨. 이를 통해 불필요한 서비스 실행을 줄이고 시스템 자원을 절약
  • D-Bus 기반 활성화(D-Bus-based Activation): D-Bus를 통해 서비스가 활성화될 수 있음.
  • On-demand 시작: 필요할 때만 서비스를 시작함
  • cgroups 지원: 서비스에 대한 리소스 제한 및 관리를 용이
  • 통합된 로깅: journald를 통해 모든 시스템 로그를 통합 관리함.
  • 유닛(Unit) 기반 관리: 모든 시스템 자원(서비스, 소켓, 장치 등)을 .unit 파일이라는 형태로 관리함.

기본 사용 방법

systemctl [OPTIONS] COMMAND [UNIT...]

자주 사용되는 command

systemctl start [UNIT] # 지정된 유닛(서비스) 시작
systemctl stop [UNIT] # 지정된 유닛(서비스) 중지
systemctl restart [UNIT] # 지정된 유닛(서비스) 재시작
systemctl reload [UNIT] # 지정된 유닛(서비스) 설정 다시 로드: 서비스를 재시작하지 않고 설정만 반영, 또한 모든 서비스가 `reload`를 지원하지는 않음.
systemctl enable [UNIT] # 지정된 유닛이 자동으로 시작되도록 설정. 심볼릭 링크를 생성하여 등록됨
systemctl disable [UNIT] # 지정된 유닛이 자동으로 시작되지 않도록 설정. enable을 통해 생성된 심볼릭 링크 삭제
systemctl status [UNIT] # 유닛의 현재 상태, 활성화 여부, 로그 등을 상세하게 보여줌
systemctl is-active [UNIT] # 유닛이 현재 활성화 중인지 여부 파악
systemctl is-enable [UNIT] # 유닛이 시스템 부팅 시 자동 시작되도록 설정되어 있는지 여부 파악
systemctl daemon-reload # systemd 관리자가 설정 파일을 다시 로드하도록 지시.

주요 유닛 파일 종류

이름 설명
.service 서비스(데몬)를 관리합니다. 가장 흔하게 사용됩니다.
.socket 소켓 기반 활성화를 위한 소켓을 정의합니다.
.device 커널에 의해 감지된 장치를 표현합니다.
.mount 파일 시스템 마운트 포인트를 정의합니다.
.automount 자동 마운트 포인트를 정의합니다.
.swap 스왑 파일을 정의합니다.
.target 다른 유닛들을 그룹화하고 특정 상태를 나타냅니다. (예: multi-user.target, graphical.target)
.path 파일 시스템 경로를 모니터링하여 다른 유닛을 활성화합니다.
.timer 타이머를 정의하여 특정 시간에 유닛을 활성화합니다.
.slice 계층적 리소스 관리 단위를 정의합니다.

유닛 파일의 주요 저장 위치

저장위치 설명
/lib/systemd/system/ 패키지 관리자에 의해 설치된 시스템 서비스 유닛 파일의 기본 경로입니다. (절대 수정하지 마세요!)
/etc/systemd/system/ 시스템 관리자가 직접 생성하거나 수정한 유닛 파일, 또는 패키지 유닛 파일에 대한 심볼릭 링크가 저장되는 경로입니다. 사용자 정의 서비스를 등록할 때 주로 이 경로를 사용합니다.
/run/systemd/system/ 런타임에 생성되는 유닛 파일의 임시 저장 경로입니다.

참고로 /etc/systemd/system에 있는 유닛 파일이 /usr/lib/systemd/system에 있는 파일보다 높은 우선순위를 가진다.


사용자 정의 서비스 직접 등록하는 방법

사용자는 자기만의 서비스를 구현하고 systemd에 등록하여 systemctl로 관리할 수도있다.


이번 챕터에서는 간단한 파이썬 스크립트를 서비스로 등록하여 systemctl로 시작/중지/재시작 해보겠다.


1. 실행할 스크립트 작성

서비스로 실행될 스크립트를 작성해주자.

스크립트는 본인이 어떤 스크립트를 작성하느냐에 따라서 달라지겠지만,

보통 백그라운드에서 계속 실행되거나, 특정 작업을 수행하고 종료하는 등의 스크립트로 작성이 될 수 있겠다.


이번 챕터에서는 간단히 로그를 기록하는 파이썬 스크립트를 예시로 사용해보겠다.


1-1. 스크립트 파일 생성

/usr/local/bin/my_custom_service.py 파일을 생성하고 다음 내용을 입력

#!/usr/bin/env python3

import time
import datetime
import sys

# 표준 출력 버퍼링 비활성화 (로그가 즉시 기록되도록)
sys.stdout.reconfigure(line_buffering=True)
sys.stderr.reconfigure(line_buffering=True)

def main():
    while True:
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f"[{timestamp}] My custom service is running...")
        time.sleep(5) # 5초마다 로그 기록

if __name__ == "__main__":
    print("My custom service started.")
    try:
        main()
    except KeyboardInterrupt:
        print("My custom service stopped.")
    except Exception as e:
        print(f"An error occurred: {e}", file=sys.stderr)
        sys.exit(1)

1-2. 스크립트 실행 권한 부여

sudo chmod +x /usr/local/bin/my_custom_service.py

2. 서비스 유닛 파일 작성

이제 systemd가 스크립트를 서비스로 인식하고 관리할 수 있도록 유닛 파일을 작성해야 한다.

이 파일은 /etc/systemd/system 디렉토리에 위치시키도록 하자.


2-1. 유닛 파일 생성

/etc/systemd/system/my-custom-service.service 파일을 생성하고 다음 내용 입력

[Unit]
Description=My Custom Python Service
After=network.target

[Service]
# 서비스 유형: simple (기본), forking (부모 프로세스가 종료되고 자식 프로세스가 백그라운드에서 실행), oneshot (명령어를 한 번 실행하고 종료), dbus, notify, idle 등
Type=simple
# 서비스가 실행할 명령어
ExecStart=/usr/local/bin/my_custom_service.py
# 스크립트가 실행될 사용자 (보안상 root 대신 전용 사용자 생성 권장)
User=your_username # 현재 사용자의 계정명으로 변경해주세요. 예: User=seungbeom
# Group=your_groupname # 선택 사항

# 서비스가 예기치 않게 종료되었을 때 systemd가 어떻게 처리할지 정의
# always: 항상 재시작
# on-failure: 비정상 종료 시 재시작
# on-abnormal: 비정상 종료 시 (시그널 등으로) 재시작
# on-watchdog: watchdog timeout 시 재시작
# on-success: 성공적으로 종료 시 재시작 (거의 사용 안 함)
# no: 재시작 안 함 (기본값)
Restart=on-failure
# Restart=always
# RestartSec=5 # 재시작 시도 전 5초 대기 (선택 사항)

# 표준 출력/오류를 journald로 리디렉션
StandardOutput=journal
StandardError=journal

[Install]
# 어떤 target에 의해 서비스가 활성화될지 정의
# multi-user.target: 일반적인 서버 환경 (GUI 없음)
# graphical.target: GUI 환경
WantedBy=multi-user.target

[UNIT] 섹션

  • Description: 서비스에 대한 간략한 설명입니다. systemctl status 명령으로 볼 수 있습니다.
  • After: 이 서비스가 시작되기 전에 먼저 시작되어야 할 유닛들을 지정합니다. network.target은 네트워크가 활성화된 후에 이 서비스가 시작되도록 보장합니다.

[Service] 섹션

  • Type: 서비스의 실행 방식을 정의합니다.
    • simple: ExecStart 명령이 주 프로세스이며, systemd는 프로세스가 시작되면 즉시 서비스가 준비되었다고 간주합니다.
    • forking: ExecStart 명령이 fork()를 통해 자식 프로세스를 생성하고 부모 프로세스가 종료됩니다. systemd는 부모 프로세스가 종료된 후 자식 프로세스를 모니터링합니다. (주로 오래된 데몬에서 사용)
    • oneshot: ExecStart 명령을 한 번 실행하고 종료됩니다. 백그라운드에서 실행되지 않는 명령에 사용됩니다.
    • notify: 서비스가 시작 완료되었음을 systemd에 알리는 특정 시그널을 보낼 때 사용합니다.
    • dbus: D-Bus 버스 이름을 획득하면 서비스가 시작됩니다.
  • ExecStart: 서비스를 시작할 때 실행될 명령어를 지정합니다. 전체 경로를 지정하는 것이 좋습니다.
  • User, Group: 이 서비스를 실행할 사용자 및 그룹을 지정합니다. 보안상 root가 아닌 일반 사용자 계정을 사용하는 것이 좋습니다.
  • Restart: 서비스가 종료되었을 때 systemd가 서비스를 어떻게 처리할지 정의합니다. on-failure는 서비스가 비정상적으로 종료되었을 때만 재시작합니다.
  • RestartSec: Restart 설정이 되어 있을 때, 재시작 시도 전에 대기할 시간을 초 단위로 지정합니다.
  • StandardOutput, StandardError: 표준 출력과 표준 오류를 어디로 리디렉션할지 지정합니다. journal로 설정하면 journalctl을 통해 로그를 확인할 수 있습니다.

[Install] 섹션

  • WantedBy: 이 서비스가 활성화(enable)될 때 어떤 target에 의해 활성화될지 정의합니다. multi-user.target은 대부분의 서버 환경에서 표준적인 다중 사용자 시스템 상태를 의미합니다.

3. systemd 설정 리로드

새로운 유닛 파일을 추가하거나 기존 유닛 파일을 수정한 후에는 systemd에게 변경 사항을 인식하도록 알려야 한다.

sudo systemctl daemon-reload

4. 서비스 활성화 및 시작

이제 서비스를 시스템 부팅 시 자동으로 시작되도록 설정하면 된다.

sudo systemctl enable my-custom-service.service

이 명령은 /etc/systemd/system/multi-user.target.wants/ 디렉토리에 my-custom-service.service에 대한 심볼릭 링크를 생성한다.


실무에서 자주 쓰는 systemctl 옵션 조합

1. 모든 실패한 failed 유닛 확인

시스템에 문제가 발생했을 때 어떤 서비스가 실패했는지 빠르게 파악하기 위함

systemctl --failed

2. 모든 활성(active) 서비스 목록 확인

현재 실행 중인 서비스들만 보려고 할 때 유용

systemctl list-units --type=service --state=running
# 또는
systemctl list-units --type=service --state=active

3. 특정 서비스의 최근 로그 확인

서비스가 시작되지 않거나 문제가 발생했을 때, 로그를 통해 특정 원인 파악하는데 필수적

journalctl -u [SERVICE_NAME]
# 특정 시간 이후 로그 확인
journalctl -u [SERVICE_NAME] --since "2 hours ago"
# 특정 날짜 이후 로그 확인
journalctl -u [SERVICE_NAME] --since "2023-01-01"
# 실시간 로그 확인 (tail -f 와 유사)
journalctl -u [SERVICE_NAME] -f

4. 서비스 유닛 파일 내용 확인

특정 유닛의 설정 파일 내용을 직접 확인하고 싶을 때 유용

systemctl cat [SERVICE_NAME].service
# 예: systemctl cat apache2.service
    Tag -

Loading script...