개요
이번 게시글에서는 작성한 쉘 스크립트를 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