Profile picture

[Linux] systemd 기반 서비스 등록 및 timer 지정해보기

JaehyoJJAng2025년 02월 15일

개요

이번 게시글에서는 작성한 쉘 스크립트를 systemd 서비스로 등록하고 timer 예약 도구를 활용하여 자동으로 실행하는 방법에 대해서 기록해보려고 합니다.

systemd는 리눅스 배포판에서 기본적으로 사용되는 초기화 시스템(init system)입니다.

서비스와 프로세스의 시작, 중지, 모니터링 등을 통합적으로 관리하는 핵심 구성요소이죠!


systemd 서비스 파일 구조

systemd 서비스는 일반적으로 .service 파일로 정의되며, 이 파일에는 서비스가 어떻게 실행될지에 대한 정보를 표시하고 있습니다.


.service 파일은 대략 다음과 같은 구조로 작성됩니다.

[Unit]
Description=서비스에 대한 설명
After=네트워크가 준비된 후 실행될 서비스

[Service]
ExecStart=실행할 명령어
ExecStop=서비스를 중지할 때 실행할 명령어 (선택적)
WorkingDirectory=서비스가 실행될 디렉토리 (선택적)
User=실행할 사용자 (선택적)
Group=실행할 그룹 (선택적)
Restart=서비스 실패 시 재시작 정책 (always, on-failure 등)

[Install]
WantedBy=multi-user.target

.service 파일에서의 주요 섹션은 다음과 같아요.

  • [Unit]: 서비스의 기본 설명이나 의존성을 설정하는 부분입니다!
  • [Service]: 실제 서비스 실행에 필요한 명령어나 그 외의 다른 설정을 합니다.
  • [Install]: 서비스의 설치를 설정합니다(multi-user.target은 서비스가 실행될 때 자동으로 실행되도록 심볼릭 링크가 생성됩니다.)

crontab 쓰는게 낫지 않나요?

쉘 스크립트를 주기적으로 사용해야 할 상황이라면 당연히 crontab이 익숙하시겠죠?


crontab을 활용해 스크립트를 주기적으로 실행하는 건 너무나 간편하고 또 익숙하기에 crontab으로 스크립트를 실행하셔도 전혀 문제가 없습니다!


하지만 systemd 기반 시스템에서는 systemd timer를 사용해서 주기적인 스크립트 실행이 가능할 뿐만 아니라 다음과 같은 이점이 있어요.

  • 로그 관리: journalctl을 통해 실행 로그 확인이 가능합니다!
  • 정확한 타이멩 제어: OnBootSec이나 OnUnitActiveSec 등 다양한 실행 시점에 대한 제어가 가능해요!
  • 상태 모니터링 가능: systemctl status로 실행 상태 및 실패 여부 확인이 가능합니다.
  • crontab 충돌 없음: 사용자/시스템별 crontab과 무관하게 관리가 가능해요!

반면에 crontab은 어떤가요?

  • 로그 수집 어려움: 별도 리다이렉션 없이는 로그 확인이 어렵고 crontab 등록 갯수가 많아지면 많아질 수록로그 파일 관리 또한 어려워져요!
  • 서비스 관리 불가: 실패 시 자동 재시작 같은 기능이 미지원이에요.

서비스 등록해보기

이번에는 서버 리소스(CPU, MEMORY, DISK)를 10마다 텔레그램으로 알림을 보내는 서비스를 등록해보려고 합니다.


스크립트 작성하기

# 설정 값
CPU_THRESHOLD=40
MEM_THRESHOLD=30
DISK_THRESHOLD=40

# 텔레그램 설정
TELEGRAM_TOKEN=
TELEGRAM_CHATID=

# CPU 사용률 계산
CPU_USAGE=$(grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {printf "%.0f", usage}')

# 메모리 사용률 계산
mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
mem_available=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
mem_used=$((mem_total - mem_available))
MEM_USAGE=$(awk "BEGIN {printf \"%.0f\", ($mem_used/$mem_total)*100}")

# '/' 디스크 사용률 계산
DISK_USAGE=$(df -h / | awk 'NR==2 {gsub("%", "", $5); print $5}')

# 알람용 텍스트
ALERT=""

# 조건 비교
[ "$CPU_USAGE" -gt "$CPU_THRESHOLD" ] && ALERT+="⚠️ CPU 사용량: ${CPU_USAGE}%\n"
[ "$MEM_USAGE" -gt "$MEM_THRESHOLD" ] && ALERT+="⚠️ 메모리 사용량: ${MEM_USAGE}%\n"
[ "$DISK_USAGE" -gt "$DISK_THRESHOLD" ] && ALERT+="⚠️ 디스크 사용량: ${DISK_USAGE}%\n"

# 알림 전송
if [ -n "$ALERT" ]; then
    MESSAGE=$(echo -e "🔔 [리소스 알림]\n$ALERT")
    curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
        -d chat_id="$TELEGRAM_CHATID" -d text="$MESSAGE" -d parse_mode="Markdown"
fi

작성 후에는, 권한을 부여해주세요 chmod +x resource.sh


서비스 파일 생성

⚠️ 주의

서비스 파일은 /etc/systemd/system/ 경로에 생성해야 systemd가 인식합니다!

파일 내용은 위에 설명드린 구조를 바탕으로 작성해주시면 됩니다.

# resource.service
[Unit]
Description=Server Resource Monitoring
After=network.target # network.target 이후에 서비스가 실행되도록 설정

[Service]
ExecStart=/bin/bash /home/jaehyo/git/systemd-script # 서비스가 시작될 때 실행할 명령어 입니다.
WorkingDirectory=/home/jaehyo # 스크립트가 실행될 디렉토리입니다.
User=root
Group=root
# 서비스를 실행할 사용자와 그룹을 지정하였습니다 (root로 통일)
Restart=on-failure
# on-failure는 서비스 실패 시 재시작하도록 설정하는 옵션이에요.
Environment=PATH=/usr/bin:/usr/local/bin

[Install]
WantedBy=multi-user.target

systemd timer 설정

systemd timer는 리눅스에서 정해진 시간이나 주기마다 서비스를 실행할 수 있도록 도와주는 기능입니다!
(.timer 유닛은 지정한 시간 조건에 따라 .service 유닛을 자동으로 실행해주는 예약 도구입니다.)

⚠️ 주의

타이머 파일은 /etc/systemd/system/ 경로에 생성해야 systemd가 인식합니다!


.timer 파일을 생성해보겠습니다. (/etc/systemd/system)

# resource.timer

[Unit]
Description=Run resource evenry 10 minutes

[Timer]
OnBootSec=5min
OnUnitActiveSec=10min
Unit=resource.service

[Install]
WantedBy=timers.target
  • OnUnitActiveSec=10min: 10분마다 실행
  • OnBootSec=5min: 부팅 후 5분 후 첫 실행

서비스 파일 권한 변경 및 활성화해주기

# 권한 부여
chmod +x /etc/systemd/system/resource.service

# 시스템에 인식시키기 위해 데몬 재시작
systemctl daemon-reexec
systemctl daemon-reload

# 서비스 활성화
systemctl enable --now resource.service
systemctl enable --now resource.timer

# 서비스 상태 확인
systemctl status resource

# 타이머 상태 화거인
systemctl list-timers --all | grep resource
    Tag -

Loading script...