# 2. 일상 운영

[목차로 돌아가기](./README.md)

---

## [운영] 전체 서비스 상태 확인

```bash
# 핵심 서비스 상태 한번에 확인
sudo systemctl status nginx php8.4-fpm mysql redis-server supervisor node_exporter

# PM2 프로세스 상태
pm2 status

# 열린 포트 확인
sudo ss -tlnp
```

## [CI/CD] 전체 서비스 상태 확인

```bash
# 모든 핵심 서비스 상태 한 번에 확인
sudo systemctl status nginx jenkins gitea mysql prometheus grafana-server node_exporter

# 개별 서비스 상태
sudo systemctl status jenkins
sudo systemctl status gitea
```

---

## [운영] .env 파일 편집 시 주의사항

> **경고:** `vi`로 `.env`를 편집하면 권한이 `600`으로 변경되어 서비스 장애가 발생할 수 있습니다.

```bash
# 편집 전 권한 확인
ls -la /home/webservice/api/shared/.env    # 640(-rw-r-----)이어야 함

# 편집 후 반드시 권한 확인 및 복원
chmod 640 /home/webservice/api/shared/.env
chmod 640 /home/webservice/mng/shared/.env
```

이를 방지하려면 `~/.vimrc`에 `set backupcopy=yes`가 설정되어 있어야 합니다.
자세한 내용: [09-security.md - .env 파일 보안](./09-security.md)

---

## [개발] sam-dev 리소스 관리

sam-dev는 2 vCPU / 3.8GB RAM으로 여러 서비스가 공존하므로 리소스 관리가 중요하다.

### 주요 리소스 소비자

| 프로세스 | 메모리 | CPU (상시) | 비고 |
|----------|--------|-----------|------|
| MySQL | ~1.2G (30%) | 2~5% | |
| Gitea | ~400M (10%) | 1.8% | |
| Next.js (PM2) | ~380M (9.5%) | 0.5% | |
| PHP 8.4 FPM | ~250M (변동) | 요청 시 높음 | max_children=5 |
| PHP 7.3 FPM | ~30M | idle | 5130 레거시 전용 |

### Swap (4G, 2026-03-09 추가)

Swap 없이 운영하면 메모리 부족 시 OOM Killer가 프로세스를 즉시 종료한다.

```bash
# Swap 상태 확인
swapon --show
free -m

# /etc/fstab에 등록되어 있으므로 재부팅 후에도 유지됨
# /swapfile none swap sw 0 0
```

### Gitea repo-archive 캐시

Gitea는 Web UI에서 ZIP/TAR.GZ 다운로드 시 `/var/lib/gitea/data/repo-archive/`에 캐시를 생성한다.
기본 설정에서는 만료가 없어 무한 증가하므로, cron으로 7일 이상 된 캐시를 정리한다.

```bash
# 캐시 크기 확인
sudo du -sh /var/lib/gitea/data/repo-archive/

# 수동 정리 (긴급 시)
sudo rm -rf /var/lib/gitea/data/repo-archive/*

# 자동 정리: hskwon crontab (매주 일요일 04:00)
# 0 4 * * 0 find /var/lib/gitea/data/repo-archive -type f -mtime +7 -delete
# 0 4 * * 0 find /var/lib/gitea/data/repo-archive -type d -empty -delete
```

### 비활성화된 서비스 (2026-03-09)

| 서비스 | 사유 | 복원 명령 |
|--------|------|----------|
| PHP 5.6 FPM | 미사용 (아무 사이트도 참조 안 함) | `sudo systemctl enable --now php5.6-fpm` |
| Apache | front.5130.co.kr 미사용 | `sudo systemctl enable --now apache2` |

---

## 시스템 리소스 모니터링

양쪽 서버 공통 명령어:

```bash
# 메모리 사용량
free -h

# 디스크 사용량
df -h

# CPU 및 프로세스 (실시간)
htop

# 로드 평균 (즉시 확인)
uptime

# 스왑 사용량
swapon --show

# 열린 포트 확인
sudo ss -tlnp

# 프로세스별 메모리 사용량 (상위 10개)
ps aux --sort=-%mem | head -11
```

**[CI/CD] 디스크 사용량 상세:**

```bash
sudo du -sh /var/lib/jenkins /var/lib/gitea /var/lib/prometheus /var/lib/mysql /var/log 2>/dev/null
```

---

## 로그 확인

### [운영] Nginx

```bash
# 접근 로그 (실시간)
sudo tail -f /var/log/nginx/api.sam.it.kr.access.log
sudo tail -f /var/log/nginx/sam.it.kr.access.log
sudo tail -f /var/log/nginx/mng.codebridge-x.com.access.log

# 에러 로그 (실시간)
sudo tail -f /var/log/nginx/api.sam.it.kr.error.log
sudo tail -f /var/log/nginx/sam.it.kr.error.log

# 최근 에러 50줄
sudo tail -50 /var/log/nginx/api.sam.it.kr.error.log
```

### [운영] PHP-FPM

```bash
sudo tail -f /var/log/php8.4-fpm.log
```

### [운영] Laravel

```bash
# API 로그
sudo tail -f /home/webservice/api/shared/storage/logs/laravel.log

# Admin(MNG) 로그 — storage/logs가 shared 심링크가 아니므로 current 경로 사용
sudo tail -f /home/webservice/mng/current/storage/logs/laravel.log

# API Stage 로그
sudo tail -f /home/webservice/api-stage/shared/storage/logs/laravel.log

# Queue Worker 로그
sudo tail -f /home/webservice/api/shared/storage/logs/queue-worker.log
```

### [운영] PM2 (Next.js)

```bash
# 운영 로그
pm2 logs sam-front --lines 50

# Stage 로그
pm2 logs sam-front-stage --lines 50

# 에러 로그만
pm2 logs sam-front --err --lines 50
```

### [운영] Supervisor

```bash
sudo supervisorctl status
sudo tail -f /home/webservice/api/shared/storage/logs/queue-worker.log
```

### [운영] MySQL

```bash
sudo tail -f /var/log/mysql/slow.log
sudo tail -f /var/log/mysql/error.log
```

### [CI/CD] Jenkins

```bash
sudo journalctl -u jenkins -f
sudo journalctl -u jenkins --since "1 hour ago"
```

### [CI/CD] Gitea

```bash
sudo journalctl -u gitea -f
sudo tail -f /var/lib/gitea/log/gitea.log
```

### [CI/CD] Prometheus / Grafana

```bash
sudo journalctl -u prometheus -f
sudo journalctl -u grafana-server -f
```

### [CI/CD] Nginx / MySQL

```bash
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/mysql/error.log
```

### 시스템 로그 (공통)

```bash
# 시스템 전체 로그 (최근)
sudo journalctl -xe --no-pager | tail -50

# 특정 서비스 로그
sudo journalctl -u 서비스명 --since "1 hour ago"
```

---

## SSL 인증서 확인 (공통)

```bash
# 전체 인증서 목록 및 만료일
sudo certbot certificates

# 자동 갱신 타이머 상태
sudo systemctl status certbot.timer

# 갱신 테스트 (실제 갱신하지 않음)
sudo certbot renew --dry-run
```

---

## [CI/CD] 네트워크 연결 확인

```bash
# 운영서버 연결
ping -c 3 211.117.60.189
ssh sam-prod "echo 'prod OK'"

# 개발서버 연결
ping -c 3 114.203.209.83
ssh sam-dev "echo 'dev OK'"

# 웹 서비스 응답 확인
curl -sI https://ci.sam.it.kr | head -5
curl -sI https://git.sam.it.kr | head -5
curl -sI https://monitor.sam.it.kr | head -5
```

---

## 일일 점검 스크립트

### [운영]

```bash
echo "=== 서비스 ===" && \
for s in nginx php8.4-fpm mysql redis-server supervisor node_exporter; do
  printf "%-20s %s\n" "$s" "$(systemctl is-active $s)"
done && \
echo "=== PM2 ===" && pm2 status && \
echo "=== 메모리 ===" && free -h | grep Mem && \
echo "=== 디스크 ===" && df -h / | tail -1 && \
echo "=== SSL ===" && sudo certbot certificates 2>/dev/null | grep "Expiry Date"
```

### [CI/CD]

```bash
echo "=== 서비스 ===" && \
for s in nginx jenkins gitea mysql prometheus grafana-server node_exporter; do
  printf "%-20s %s\n" "$s" "$(systemctl is-active $s)"
done && \
echo "=== 메모리 ===" && free -h | grep Mem && \
echo "=== 디스크 ===" && df -h / | tail -1 && \
echo "=== SSL ===" && sudo certbot certificates 2>/dev/null | grep "Expiry Date"
```