실전: 설정 파일 자동 수정
서버 설정 파일을 배포할 때마다 수작업으로 열어서 수정하는 일은 번거롭고 실수가 생깁니다. 개발 환경과 운영 환경에서 포트, 도메인, 경로가 달라지는 경우라면 더욱 그렇습니다. 이런 반복 작업을 sed 스크립트 하나로 해결할 수 있습니다.
시나리오
nginx 설정 파일을 배포 환경에 맞게 자동으로 수정하는 스크립트를 만들겠습니다. 아래 작업을 수행합니다.
- 포트 변경 (80 → 8080)
- 도메인 변경 (example.com → myapp.com)
- 주석 처리된 설정 활성화 (gzip 설정)
- 새 설정 블록 추가 (보안 헤더)
- 백업 생성 후 수정, 오류 시 롤백
샘플 설정 파일
먼저 수정 대상 nginx.conf를 준비합니다.
# 파일: /tmp/nginx.confcat > /tmp/nginx.conf << 'EOF'server { listen 80; server_name example.com www.example.com; root /var/www/html; index index.html; # gzip 압축 (필요시 활성화) # gzip on; # gzip_types text/plain text/css application/json; location / { try_files $uri $uri/ =404; } location /api { proxy_pass http://localhost:3000; proxy_http_version 1.1; }}EOF
수정 스크립트
# 파일: /tmp/config_modifier.sh#!/bin/bash# nginx.conf 자동 수정 스크립트# 사용법: ./config_modifier.sh <설정파일> <새포트> <새도메인>set -euo pipefailCONFIG_FILE="${1:-/tmp/nginx.conf}"NEW_PORT="${2:-8080}"NEW_DOMAIN="${3:-myapp.com}"# ──────────────────────────────────────────# 함수 정의# ──────────────────────────────────────────log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"}error() { echo "[ERROR] $*" >&2}# ──────────────────────────────────────────# 검증# ──────────────────────────────────────────if [[ ! -f "$CONFIG_FILE" ]]; then error "설정 파일이 없습니다: $CONFIG_FILE" exit 1filog "설정 파일 수정 시작: $CONFIG_FILE"# ──────────────────────────────────────────# 백업# ──────────────────────────────────────────BACKUP_FILE="${CONFIG_FILE}.bak.$(date '+%Y%m%d_%H%M%S')"cp "$CONFIG_FILE" "$BACKUP_FILE"log "백업 완료: $BACKUP_FILE"# ──────────────────────────────────────────# 수정 작업 (임시 파일 사용)# ──────────────────────────────────────────TEMP_FILE=$(mktemp)sed \ -e "s/listen [0-9]\+;/listen ${NEW_PORT};/" \ -e "s/server_name [^;]\+;/server_name ${NEW_DOMAIN} www.${NEW_DOMAIN};/" \ -e "s|# gzip on;|gzip on;|" \ -e "s|# gzip_types|gzip_types|" \ "$CONFIG_FILE" > "$TEMP_FILE"# ──────────────────────────────────────────# 보안 헤더 블록 추가 (location /api 앞에 삽입)# ──────────────────────────────────────────sed -i "/location \/api/i\\ # Security headers\\n add_header X-Frame-Options DENY;\\n add_header X-Content-Type-Options nosniff;" \ "$TEMP_FILE"# ──────────────────────────────────────────# 검증: 필수 항목 확인# ──────────────────────────────────────────ERRORS=0if ! grep -q "listen ${NEW_PORT};" "$TEMP_FILE"; then error "포트 변경 실패" ERRORS=$((ERRORS + 1))fiif ! grep -q "server_name ${NEW_DOMAIN}" "$TEMP_FILE"; then error "도메인 변경 실패" ERRORS=$((ERRORS + 1))fiif ! grep -q "gzip on;" "$TEMP_FILE"; then error "gzip 활성화 실패" ERRORS=$((ERRORS + 1))fi# ──────────────────────────────────────────# 결과 처리# ──────────────────────────────────────────if [[ $ERRORS -gt 0 ]]; then error "오류 $ERRORS건 발생. 원본으로 롤백합니다." cp "$BACKUP_FILE" "$CONFIG_FILE" rm -f "$TEMP_FILE" exit 1fi# 성공 시 임시 파일을 원본 위치로 이동mv "$TEMP_FILE" "$CONFIG_FILE"log "설정 파일 수정 완료."log "변경 사항:"log " 포트: 80 → ${NEW_PORT}"log " 도메인: example.com → ${NEW_DOMAIN}"log " gzip 압축 활성화"log " 보안 헤더 추가"log "백업 위치: $BACKUP_FILE"
실행 결과
chmod +x /tmp/config_modifier.sh/tmp/config_modifier.sh /tmp/nginx.conf 8080 myapp.com
[2024-03-15 10:30:00] 설정 파일 수정 시작: /tmp/nginx.conf
[2024-03-15 10:30:00] 백업 완료: /tmp/nginx.conf.bak.20240315_103000
[2024-03-15 10:30:00] 설정 파일 수정 완료.
[2024-03-15 10:30:00] 변경 사항:
[2024-03-15 10:30:00] 포트: 80 → 8080
[2024-03-15 10:30:00] 도메인: example.com → myapp.com
[2024-03-15 10:30:00] gzip 압축 활성화
[2024-03-15 10:30:00] 보안 헤더 추가
[2024-03-15 10:30:00] 백업 위치: /tmp/nginx.conf.bak.20240315_103000
수정된 파일을 확인합니다.
cat /tmp/nginx.conf
server {
listen 8080;
server_name myapp.com www.myapp.com;
root /var/www/html;
index index.html;
# gzip 압축 (필요시 활성화)
gzip on;
gzip_types text/plain text/css application/json;
location / {
try_files $uri $uri/ =404;
}
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
location /api {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
}
}
롤백 확인
오류가 발생했을 때 원본이 복구되는지 확인합니다.
# 의도적으로 잘못된 패턴 테스트를 위해 백업에서 복원cp /tmp/nginx.conf.bak.20240315_103000 /tmp/nginx.conf# 백업 파일에서 원본 내용 확인diff /tmp/nginx.conf /tmp/nginx.conf.bak.20240315_103000
(차이 없음 - 동일한 파일)
스크립트 핵심 포인트
임시 파일 패턴. 직접 -i로 원본을 수정하지 않고 mktemp로 임시 파일을 만든 뒤 검증 후에 원본 위치로 mv합니다. 수정 중 오류가 나도 원본은 안전합니다.
set -euo pipefail. 오류 발생 시 즉시 종료하고, 미정의 변수 참조를 금지하고, 파이프라인 오류를 전파합니다. 스크립트가 예기치 않게 계속 실행되는 상황을 막습니다.
검증 단계. 수정 후 반드시 결과를 확인합니다. grep으로 필수 항목이 존재하는지 검사하고, 없으면 ERRORS를 누적합니다. ERRORS가 0이 아니면 롤백합니다.
타임스탬프 백업. 백업 파일명에 날짜와 시간을 붙여 여러 번 실행해도 백업이 덮어씌워지지 않게 합니다.
sed 하나로 이렇게 많은 일을 할 수 있습니다. 다음 장에서는 sed보다 훨씬 강력한 텍스트 처리 언어, awk를 만나보겠습니다.