들어가며: 로그, 서버의 블랙박스

로그는 서버에서 일어나는 모든 일을 기록합니다. 문제 발생 시 원인 파악, 보안 감사, 성능 분석 등 로그 관리는 서버 운영의 핵심입니다.

1. Linux 로그 시스템 이해

1.1 주요 로그 파일

/var/log/syslog        # 시스템 로그 (Debian/Ubuntu)
/var/log/messages      # 시스템 로그 (RHEL/CentOS)
/var/log/auth.log      # 인증 로그 (Debian/Ubuntu)
/var/log/secure        # 인증 로그 (RHEL/CentOS)
/var/log/kern.log      # 커널 로그
/var/log/dmesg         # 부팅 메시지
/var/log/cron          # 크론 작업 로그
/var/log/maillog       # 메일 서버 로그
/var/log/nginx/        # Nginx 로그
/var/log/apache2/      # Apache 로그
/var/log/mysql/        # MySQL 로그

1.2 로그 레벨

0: emerg   # 시스템 사용 불가
1: alert   # 즉각적인 조치 필요
2: crit    # 심각한 상태
3: err     # 에러 상태
4: warning # 경고 상태
5: notice  # 정상이지만 중요한 상태
6: info    # 정보성 메시지
7: debug   # 디버그 메시지

2. systemd-journald

2.1 journalctl 기본 사용

# 전체 로그 보기
journalctl

# 최근 로그부터 (역순)
journalctl -r

# 마지막 n개 줄
journalctl -n 50

# 실시간 추적
journalctl -f

# 부팅 이후 로그
journalctl -b

# 이전 부팅 로그
journalctl -b -1

2.2 필터링

# 서비스별 로그
journalctl -u nginx
journalctl -u mysql.service

# 우선순위별
journalctl -p err          # 에러 이상
journalctl -p warning..err # 범위 지정

# 시간별
journalctl --since "2026-01-20"
journalctl --since "1 hour ago"
journalctl --since "2026-01-20 09:00" --until "2026-01-20 18:00"

# 사용자별
journalctl _UID=1000

# 프로세스별
journalctl _PID=1234

# 커널 메시지
journalctl -k

2.3 출력 형식

# JSON 형식
journalctl -o json
journalctl -o json-pretty

# 간단한 형식
journalctl -o short
journalctl -o short-iso

# 상세 형식
journalctl -o verbose

2.4 저널 관리

# 디스크 사용량 확인
journalctl --disk-usage

# 오래된 로그 정리
journalctl --vacuum-time=7d    # 7일 이전 삭제
journalctl --vacuum-size=500M  # 500MB로 제한

# 설정 파일: /etc/systemd/journald.conf
[Journal]
Storage=persistent
Compress=yes
SystemMaxUse=500M
MaxRetentionSec=1month

3. rsyslog

3.1 설정 파일

# /etc/rsyslog.conf 주요 설정

# 모듈 로드
module(load="imuxsock")    # 로컬 시스템 로깅
module(load="imklog")      # 커널 로깅

# 로그 규칙: facility.priority  action
*.info;mail.none;authpriv.none  /var/log/messages
authpriv.*                       /var/log/secure
mail.*                          /var/log/maillog
cron.*                          /var/log/cron
*.emerg                         :omusrmsg:*

# 원격 로깅
*.* @@192.168.1.100:514    # TCP
*.* @192.168.1.100:514     # UDP

3.2 사용자 정의 로그

# /etc/rsyslog.d/myapp.conf
if $programname == 'myapp' then /var/log/myapp.log
& stop

# 재시작
sudo systemctl restart rsyslog

# 로그 테스트
logger -t myapp "테스트 메시지"

4. logrotate

4.1 기본 설정

# /etc/logrotate.conf
weekly              # 주간 로테이션
rotate 4            # 4개 보관
create              # 새 파일 생성
dateext             # 날짜 확장자
compress            # 압축

include /etc/logrotate.d

4.2 애플리케이션별 설정

# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
    copytruncate
}

4.3 수동 실행

# 테스트 (실제 실행 안 함)
logrotate -d /etc/logrotate.conf

# 강제 실행
logrotate -f /etc/logrotate.conf

# 특정 설정만 실행
logrotate -f /etc/logrotate.d/nginx

5. 실시간 로그 모니터링

5.1 tail과 grep

# 실시간 모니터링
tail -f /var/log/syslog

# 여러 파일 동시 모니터링
tail -f /var/log/nginx/access.log /var/log/nginx/error.log

# 필터링
tail -f /var/log/syslog | grep -i error
tail -f /var/log/auth.log | grep "Failed password"

# 색상 하이라이트
tail -f /var/log/syslog | grep --color=always -E "error|warning|"

5.2 multitail

# 설치
sudo apt install multitail

# 여러 로그 동시 모니터링
multitail /var/log/syslog /var/log/auth.log

# 색상 스키마 적용
multitail -cS apache /var/log/apache2/access.log

5.3 모니터링 스크립트

#!/bin/bash
# log_alert.sh - 에러 발생 시 알림

LOG_FILE="/var/log/syslog"
KEYWORDS="error|critical|failed"
EMAIL="admin@example.com"

tail -Fn0 "$LOG_FILE" | while read line; do
    if echo "$line" | grep -qiE "$KEYWORDS"; then
        echo "$line" | mail -s "서버 알림: 로그 이상 감지" "$EMAIL"
    fi
done

6. 로그 분석

6.1 기본 분석 명령

# 에러 카운트
grep -c "error" /var/log/syslog

# 에러 유형별 분류
grep -i error /var/log/syslog | awk '{print $5}' | sort | uniq -c | sort -rn

# 시간대별 로그 수
awk '{print $1, $2, $3}' /var/log/syslog | cut -d: -f1 | uniq -c

# IP별 접속 횟수 (웹 서버)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

# 상태 코드별 분류
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 404 에러 URL
awk '$9 == 404 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

6.2 로그 분석 스크립트

#!/bin/bash
# web_log_report.sh

LOG="/var/log/nginx/access.log"

echo "=== 웹 로그 분석 리포트 ==="
echo "기간: $(head -1 $LOG | awk '{print $4}') ~ $(tail -1 $LOG | awk '{print $4}')"
echo ""

echo "--- 총 요청 수 ---"
wc -l < "$LOG"

echo ""
echo "--- 상위 10개 IP ---"
awk '{print $1}' "$LOG" | sort | uniq -c | sort -rn | head -10

echo ""
echo "--- HTTP 상태 코드 ---"
awk '{print $9}' "$LOG" | sort | uniq -c | sort -rn

echo ""
echo "--- 상위 10개 URL ---"
awk '{print $7}' "$LOG" | sort | uniq -c | sort -rn | head -10

echo ""
echo "--- 시간대별 요청 ---"
awk '{print substr($4,14,2)":00"}' "$LOG" | sort | uniq -c

7. 시스템 모니터링

7.1 시스템 리소스

# CPU, 메모리 실시간
top
htop

# 메모리 상세
free -h
vmstat 1

# 디스크 I/O
iostat -x 1
iotop

# 네트워크
netstat -tuln
ss -tuln
iftop

# 프로세스별 리소스
ps aux --sort=-%mem | head
ps aux --sort=-%cpu | head

7.2 시스템 상태 스크립트

#!/bin/bash
# system_status.sh

echo "=== 시스템 상태 리포트 ==="
echo "시간: $(date)"
echo ""

echo "--- 시스템 정보 ---"
uptime
echo ""

echo "--- CPU 사용률 ---"
top -bn1 | grep "Cpu(s)" | awk '{print "사용률:", 100-$8"%"}'
echo ""

echo "--- 메모리 ---"
free -h | grep Mem
echo ""

echo "--- 디스크 ---"
df -h | grep -E "^/dev"
echo ""

echo "--- 로드 평균 ---"
cat /proc/loadavg
echo ""

echo "--- 상위 5개 CPU 프로세스 ---"
ps aux --sort=-%cpu | head -6

echo ""
echo "--- 상위 5개 메모리 프로세스 ---"
ps aux --sort=-%mem | head -6

8. 알림 설정

8.1 메일 알림

#!/bin/bash
# disk_alert.sh

THRESHOLD=80
EMAIL="admin@example.com"

df -h | grep -vE '^Filesystem|tmpfs' | while read line; do
    usage=$(echo "$line" | awk '{print $5}' | sed 's/%//')
    partition=$(echo "$line" | awk '{print $6}')

    if [ "$usage" -ge "$THRESHOLD" ]; then
        echo "경고: $partition 사용량 ${usage}%" | \
            mail -s "디스크 경고: $(hostname)" "$EMAIL"
    fi
done

8.2 cron으로 자동화

# crontab -e
# 매 시간 디스크 체크
0 * * * * /root/scripts/disk_alert.sh

# 매일 로그 리포트
0 8 * * * /root/scripts/web_log_report.sh | mail -s "일일 로그 리포트" admin@example.com

# 5분마다 서비스 상태 확인
*/5 * * * * /root/scripts/service_check.sh

9. 중앙 집중식 로그 관리

9.1 원격 rsyslog 서버

# 서버 설정 (/etc/rsyslog.conf)
module(load="imudp")
input(type="imudp" port="514")

module(load="imtcp")
input(type="imtcp" port="514")

# 클라이언트별 로그 분리
$template RemoteLogs,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
*.* ?RemoteLogs

# 클라이언트 설정
*.* @@log-server:514

9.2 ELK 스택 (개요)

# Elasticsearch: 로그 저장 및 검색
# Logstash: 로그 수집 및 처리
# Kibana: 시각화 대시보드

# Filebeat로 로그 수집
# /etc/filebeat/filebeat.yml
filebeat.inputs:
  - type: log
    paths:
      - /var/log/*.log
      - /var/log/nginx/*.log

output.elasticsearch:
  hosts: ["localhost:9200"]

10. 실습: 종합 모니터링 시스템

#!/bin/bash
# comprehensive_monitor.sh

LOG_DIR="/var/log/monitoring"
mkdir -p "$LOG_DIR"

# 시스템 상태 기록
{
    echo "=== $(date) ==="
    echo "Uptime: $(uptime)"
    echo "Load: $(cat /proc/loadavg)"
    echo "Memory: $(free -m | grep Mem)"
    echo "Disk: $(df -h / | tail -1)"
} >> "$LOG_DIR/system_$(date +%Y%m%d).log"

# 서비스 상태 확인
for service in nginx mysql redis; do
    if ! systemctl is-active --quiet "$service"; then
        echo "[$(date)] $service down" >> "$LOG_DIR/alerts.log"
    fi
done

# 로그 에러 카운트
ERROR_COUNT=$(grep -c "error" /var/log/syslog 2>/dev/null || echo 0)
echo "$(date),errors,$ERROR_COUNT" >> "$LOG_DIR/metrics.csv"

마무리

로그 관리와 모니터링은 서버 운영의 핵심입니다. 적절한 로그 설정, 정기적인 분석, 자동화된 알림으로 문제를 사전에 감지하고 대응할 수 있습니다. 다음 편에서는 백업과 복구 전략을 다룹니다.