systemd 서비스 제어 및 유닛 파일 작성
systemctl로 서비스를 제어하고 스크립트로 실행되는 데몬을 위한 사용자 지정 유닛 및 타이머 파일을 작성합니다.
systemd 서비스 제어 및 유닛 파일 작성은(는) CoddyKit의 무료 DevOps Bootcamp 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 DevOps Bootcamp 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. DevOps Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.
systemd 및 systemctl 소개
systemd는 대부분의 최신 Linux 배포판에서 사용하는 초기화 시스템이자 서비스 관리자입니다. 시스템 서비스를 시작, 중지, 관리하고 부팅 순서와 시스템 상태를 처리합니다.
systemd와 상호 작용하는 기본 도구는 systemctl입니다. 이를 사용하면 다음을 수행할 수 있습니다.
- 서비스를 시작하고 중지합니다.
- 부팅 시 서비스를 활성화하거나 비활성화합니다.
- 서비스 상태와 로그를 확인합니다.
- 다시 시작하지 않고 구성을 다시 불러옵니다.
systemd가 관리하는 모든 서비스는 유닛 파일에 정의됩니다. 유닛 파일은 /etc/systemd/system/(시스템 전체) 또는 ~/.config/systemd/user/(사용자별)에 저장되는 선언적 구성 파일입니다.
필수 systemctl 명령
다음은 일상적인 서비스 관리에 가장 자주 사용하는 systemctl 명령입니다. 각 명령은 nginx.service 또는 간단히 nginx와 같은 유닛 이름을 대상으로 작동합니다.
systemctl start <unit>— 서비스를 즉시 시작합니다systemctl stop <unit>— 실행 중인 서비스를 중지합니다systemctl restart <unit>— 중지한 다음 시작합니다(완전히 다시 시작)systemctl reload <unit>— 서비스를 중지하지 않고 설정을 다시 불러오도록 SIGHUP을 보냅니다systemctl enable <unit>— 부팅 시 유닛이 시작되도록 심볼릭 링크를 생성합니다systemctl disable <unit>— 해당 심볼릭 링크를 제거합니다systemctl status <unit>— 상태, PID, 최근 로그 행을 표시합니다
#!/usr/bin/env bash
# Quick reference: inspect and control an nginx service
# (Requires nginx to be installed; run as root or with sudo)
systemctl status nginx
systemctl start nginx
systemctl enable nginx
systemctl reload nginx
systemctl restart nginx
systemctl stop nginx
systemctl disable nginx서비스 상태 자세히 확인하기
systemctl status는 유닛의 다양한 정보를 한눈에 보여 줍니다. 출력을 이해하면 문제를 신속하게 진단하는 데 큰 도움이 됩니다.
- Loaded: 유닛 파일의 경로와 부팅 시 활성화 여부
- Active: 현재 상태 —
active (running),inactive (dead),failed - Main PID: 서비스 주 프로세스의 프로세스 식별자
- CGroup: 서비스에 속한 모든 하위 프로세스
- Log lines: 이 유닛에 대한 최근 저널 항목
systemctl is-active를 사용하면 활성 상태만 조회할 수 있고, systemctl is-enabled를 사용하면 활성화 상태만 조회할 수 있습니다. 두 명령 모두 스크립트에서 사용하기에 적합합니다.
#!/usr/bin/env bash
# Script-friendly service health check
SERVICE="sshd"
if systemctl is-active --quiet "$SERVICE"; then
echo "$SERVICE is running."
else
echo "$SERVICE is NOT running. Attempting restart..."
systemctl restart "$SERVICE"
fi
if systemctl is-enabled --quiet "$SERVICE"; then
echo "$SERVICE is enabled at boot."
else
echo "WARNING: $SERVICE is not enabled at boot."
fi유닛 나열 및 필터링
많은 서비스를 관리할 때는 유닛을 효율적으로 나열하고 필터링할 방법이 필요합니다. systemctl list-units는 현재 로드된 모든 유닛을 보여 주고, list-unit-files는 설치된 모든 유닛 파일과 활성화 상태를 보여 줍니다.
유용한 필터링 옵션은 다음과 같습니다.
--type=service— 서비스 유닛만 표시합니다--state=failed— 실패한 유닛만 표시합니다--state=active— 활성 유닛만 표시합니다--all— 비활성 유닛도 목록에 포함합니다
이러한 필터를 grep과 함께 사용하면 유지 관리 스크립트에서 강력한 검사 파이프라인을 구성할 수 있습니다.
#!/usr/bin/env bash
# List all failed services and report them
echo "=== Failed Services ==="
systemctl list-units --type=service --state=failed --no-legend
echo ""
echo "=== Services Enabled at Boot ==="
systemctl list-unit-files --type=service --state=enabled --no-legend | awk '{print $1}'systemd 서비스 유닛 파일의 구조
서비스 유닛 파일은 여러 섹션으로 구성된 일반 텍스트 INI 형식 파일입니다. 각 섹션은 유닛 수명 주기의 서로 다른 측면을 제어합니다.
- [Unit] — 메타데이터: 설명 및 순서 지정 종속성(
After=,Requires=,Wants=) - [Service] — 프로세스 시작 및 중지 방법:
ExecStart,ExecStop,Restart,User,WorkingDirectory - [Install] — 이 유닛을 활성화할 시점:
WantedBy=multi-user.target는 일반적인 다중 사용자 부팅 중에 활성화된다는 뜻입니다
/etc/systemd/system/ 아래에 유닛 파일을 배치하거나 편집한 후에는 systemd가 변경 사항을 반영하도록 systemctl daemon-reload를 실행해야 합니다.
첫 서비스 유닛 파일 작성하기
사용자 지정 Python HTTP 서버 스크립트를 위한 간단한 서비스 유닛 파일을 만들어 보겠습니다. 이 유닛 파일은 다른 시스템 서비스와 마찬가지로 systemd가 이 프로세스를 정확히 관리하는 방법을 지정합니다.
여기서 사용하는 주요 [Service] 지시어는 다음과 같습니다.
Type=simple— systemd가ExecStart프로세스를 주 프로세스로 취급합니다User=www-data— 보안을 위해 루트가 아닌 계정으로 실행합니다WorkingDirectory— 프로세스의 작업 디렉터리를 지정합니다Restart=on-failure— 프로세스가 0이 아닌 코드로 종료되면 자동으로 다시 시작합니다RestartSec=5— 다시 시작을 시도하기 전에 5초 동안 기다립니다
#!/usr/bin/env bash
# Create a custom service unit file for a simple HTTP server
# Run as root
cat > /etc/systemd/system/mywebserver.service << 'EOF'
[Unit]
Description=My Custom Python Web Server
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/mysite
ExecStart=/usr/bin/python3 -m http.server 8080
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now mywebserver.service
systemctl status mywebserver.service서비스 유형과 프로세스 수명 주기
[Service]의 Type= 지시어는 서비스 시작이 완료된 시점을 systemd가 추적하는 방법을 지정합니다. 잘못된 유형을 선택하면 순서 지정 문제가 자주 발생합니다.
Type=simple— 기본값입니다.ExecStart가 실행되자마자 systemd는 서비스가 시작된 것으로 간주합니다. 준비 완료 신호는 필요하지 않습니다.Type=forking—ExecStart프로세스가 분기된 후 종료되고, 실제 데몬은 하위 프로세스로 실행됩니다. systemd가 이를 추적할 수 있도록PIDFile=을 사용합니다.Type=notify— 프로세스가 실제로 준비되면sd_notify(READY=1)을 보냅니다. 복잡한 데몬에 가장 안정적입니다.Type=oneshot— 한 번 실행한 후 종료되며, 이후 유닛은 완료될 때까지 기다립니다. 설정 스크립트에 적합합니다.Type=idle— simple과 비슷하지만 현재 활성화된 모든 작업이 끝날 때까지 실행이 지연됩니다.
#!/usr/bin/env bash
# Example: oneshot service for a database migration script
# /etc/systemd/system/db-migrate.service
cat > /etc/systemd/system/db-migrate.service << 'EOF'
[Unit]
Description=Run Database Migrations
After=postgresql.service
Requires=postgresql.service
[Service]
Type=oneshot
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/scripts/migrate.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start db-migrate.service환경 변수와 보안 강화
서비스 유닛 파일은 환경 변수를 전달하고 보안 제한을 적용하기 위한 여러 지시어를 지원합니다. 두 가지 모두 운영 환경에서 중요합니다.
환경 지시어:
Environment="KEY=value"— 인라인으로 변수 하나를 설정합니다EnvironmentFile=/etc/myapp/env— 파일에서 변수를 불러옵니다(각 행에KEY=value하나씩 지정)
일반적인 보안 강화 지시어:
NoNewPrivileges=true— setuid를 통해 프로세스가 추가 권한을 얻지 못하게 합니다ProtectSystem=strict—/usr,/boot,/etc를 읽기 전용으로 마운트합니다PrivateTmp=true— 서비스에 격리된 자체/tmp를 제공합니다CapabilityBoundingSet=— 모든 Linux 기능을 제거합니다
#!/usr/bin/env bash
# Hardened service unit with environment file
cat > /etc/systemd/system/secureapp.service << 'EOF'
[Unit]
Description=Secure Application Daemon
After=network.target
[Service]
Type=simple
User=secureapp
Group=secureapp
WorkingDirectory=/opt/secureapp
EnvironmentFile=/etc/secureapp/env
ExecStart=/opt/secureapp/bin/server
Restart=on-failure
RestartSec=10
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
CapabilityBoundingSet=
ReadWritePaths=/var/lib/secureapp /var/log/secureapp
[Install]
WantedBy=multi-user.target
EOF
# Create the environment file separately so secrets stay out of the unit file
install -m 600 -o secureapp /dev/null /etc/secureapp/env
echo 'APP_PORT=9000' >> /etc/secureapp/env
echo 'DB_URL=postgresql://localhost/mydb' >> /etc/secureapp/env
systemctl daemon-reloadsystemd 타이머 유닛 소개
systemd 타이머는 일정에 따라 다른 유닛(일반적으로 .service)을 활성화하는 유닛입니다. 기존 cron 작업을 더 통합적이고 로그를 기록할 수 있으며 제어하기 쉬운 방식으로 대체합니다.
모든 타이머 유닛(foo.timer)에는 동일한 기본 이름을 가진 서비스 유닛(foo.service)이 연결되며, 실제 작업은 서비스 유닛이 수행합니다. 직접 서비스가 아니라 타이머를 활성화하고 시작해야 합니다.
타이머 유형:
- 실시간(달력) 타이머 —
OnCalendar=표현식을 사용해daily,weekly,Mon *-*-* 02:00:00과 같은 시계 시간에 실행됩니다 - 단조 시간 타이머 —
OnBootSec=,OnActiveSec=또는OnUnitActiveSec=을 사용해 시스템 이벤트를 기준으로 실행됩니다
타이머 유닛 파일 작성하기
매일 02:00에 백업 스크립트를 실행하는 완전한 타이머와 서비스 쌍을 만들어 보겠습니다. [Timer] 섹션은 별도의 .timer 파일에 있고 실제 작업은 연결된 .service 파일에 있다는 점에 유의하세요.
주요 [Timer] 지시어는 다음과 같습니다.
OnCalendar=— 일정을 지정하는 달력 표현식Persistent=true— 타이머가 실행되어야 할 때 시스템이 꺼져 있었다면 다음 부팅 시 즉시 실행합니다RandomizedDelaySec=— 여러 호스트가 같은 일정을 공유할 때 동시 실행 폭주를 방지하도록 최대 N초의 무작위 지연을 추가합니다Unit=— 명시적인 대상 유닛입니다(이름이 일치하면 선택 사항)
#!/usr/bin/env bash
# Create a daily backup timer pair
# Run as root
# 1. The service that does the work
cat > /etc/systemd/system/daily-backup.service << 'EOF'
[Unit]
Description=Daily Database Backup
After=network.target postgresql.service
[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup-db.sh
StandardOutput=journal
StandardError=journal
EOF
# 2. The timer that schedules it
cat > /etc/systemd/system/daily-backup.timer << 'EOF'
[Unit]
Description=Run Daily Database Backup at 02:00
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable --now daily-backup.timer
# Verify
systemctl list-timers daily-backup.timer로그 검사 및 유닛 문제 해결
systemd는 모든 서비스 출력을 저널로 보내며, journalctl을 사용해 이를 조회할 수 있습니다. 따라서 모든 유닛의 로그를 검색 가능한 하나의 저장소에서 중앙 집중식으로 관리할 수 있습니다.
서비스 문제 해결에 필요한 주요 journalctl 옵션은 다음과 같습니다.
-u <unit>— 유닛 이름으로 필터링합니다-f— 로그를 실시간으로 따라갑니다(tail -f와 유사)-n 50— 마지막 50개 행만 표시합니다--since "1 hour ago"— 시간 범위를 제한합니다-p err— 오류 우선순위 이상만 표시합니다-b— 현재 부팅에서 생성된 로그만 표시합니다
유닛이 시작되지 않으면 먼저 journalctl -u <unit> -n 30 --no-pager를 실행한 다음 systemctl status <unit>를 실행하여 최근 오류 상황을 확인하세요.
#!/usr/bin/env bash
# Troubleshooting helper: dump unit status and recent logs
# Usage: ./service-debug.sh <unit-name>
UNIT="${1:-nginx.service}"
echo "=============================="
echo "STATUS: $UNIT"
echo "=============================="
systemctl status "$UNIT" --no-pager -l
echo ""
echo "=============================="
echo "RECENT LOGS (last 50 lines): $UNIT"
echo "=============================="
journalctl -u "$UNIT" -n 50 --no-pager
echo ""
echo "=============================="
echo "ERRORS ONLY (current boot)"
echo "=============================="
journalctl -u "$UNIT" -b -p err --no-pager지식 확인: systemd 유닛 파일
systemd 서비스 및 타이머 유닛 구성에 대한 이해도를 확인해 보세요.
단원 요약: systemd 서비스 제어 및 유닛 파일 작성
이 단원에서는 전문적인 수준에서 systemd 서비스 관리와 유닛 파일 작성의 핵심 개념을 살펴보았습니다. 학습한 내용을 요약하면 다음과 같습니다.
- systemctl 기초 — 스크립트에서 사용하기 쉬운 검사 기능을 위한 start, stop, restart, reload, enable, disable, status, is-active, is-enabled
- 나열 및 필터링 —
list-units와list-unit-files에--type및--state옵션을 사용하여 실패했거나 활성화된 서비스를 구분합니다 - 유닛 파일 구조 —
[Unit],[Service],[Install]의 세 섹션과 주요 지시어 - 서비스 유형 —
simple,forking,notify,oneshot및 각 유형의 사용 시점 - 환경 및 보안 — 강화된 데몬을 위한
EnvironmentFile,NoNewPrivileges,ProtectSystem,PrivateTmp - 타이머 유닛 —
.timer와.service파일 연결,OnCalendar표현식,Persistent의 누락 실행 보완 동작 - Journalctl — 장애를 효율적으로 진단하기 위한 유닛, 시간, 부팅, 우선순위별 필터링
이러한 기술을 익히면 모든 시스템 서비스를 관리하고, 반복 작업을 안정적으로 예약하며, 직접 만든 데몬을 위한 운영 환경 수준의 유닛 파일을 작성할 수 있습니다.
자주 묻는 질문
“systemd 서비스 제어 및 유닛 파일 작성” 강의는 무료인가요?
네 — “systemd 서비스 제어 및 유닛 파일 작성” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 DevOps Bootcamp 강의 전체를 잠금 해제할 수 있습니다. DevOps Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.
“systemd 서비스 제어 및 유닛 파일 작성”에서 뭘 배우나요?
systemctl로 서비스를 제어하고 스크립트로 실행되는 데몬을 위한 사용자 지정 유닛 및 타이머 파일을 작성합니다. 브라우저에서 직접 실행하는 실습 코드로 DevOps Bootcamp을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
DevOps Bootcamp을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 DevOps Bootcamp은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“systemd 서비스 제어 및 유닛 파일 작성” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 DevOps Bootcamp 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 DevOps Bootcamp 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 사용자 및 그룹 프로비저닝 자동화
- systemd 서비스 제어 및 유닛 파일 작성
- 디스크, 파일 시스템 및 마운트 자동화
- 시스템 상태 점검 및 알림 스크립트 구축