홈 › 리눅스 운영 › 05 / 13

Tomcat·nginx 배포·재기동

섹션 7진행 0 / 13

3. 코드 예제

예제 1: Tomcat 정지·시작 함수 — tomcat_deploy.sh 발췌

bash
have_systemd() { systemctl list-unit-files "$TOMCAT_SERVICE.service" 2>/dev/null | grep -q "$TOMCAT_SERVICE"; }

tomcat_stop() {
  if have_systemd; then systemctl stop "$TOMCAT_SERVICE"; return; fi
  "$CATALINA_HOME/bin/shutdown.sh"
  for _ in $(seq 1 "$STOP_WAIT"); do
    pgrep -f "catalina.base=$CATALINA_BASE" >/dev/null || return 0
    sleep 1
  done
  pkill -9 -f "catalina.base=$CATALINA_BASE"
}
tomcat_start() {
  if have_systemd; then systemctl start "$TOMCAT_SERVICE"; else "$CATALINA_HOME/bin/startup.sh"; fi
}

유닛이 있으면 systemctl, 없으면 catalina 스크립트를 쓰도록 한 함수에 묶었습니다. 호출하는 쪽은 서버가 어느 방식인지 몰라도 됩니다.

예제 2: 배포 본문 — tomcat_deploy.sh 발췌

bash
WAR=${1:?사용: $0 <war> [컨텍스트]}
CTX=${2:-$(basename "$WAR" .war)}
STAMP=$(date +%Y%m%d_%H%M%S)
[ -f "$WEBAPPS/$CTX.war" ] && cp "$WEBAPPS/$CTX.war" "$BACKUP_DIR/$CTX.war.$STAMP"
tomcat_stop
rm -rf "$WEBAPPS/$CTX" "$WEBAPPS/$CTX.war"
rm -rf "$CATALINA_BASE/work/Catalina/localhost/$CTX"
cp "$WAR" "$WEBAPPS/$CTX.war"
tomcat_start
wait_health || { echo "롤백: $BACKUP_DIR/$CTX.war.$STAMP"; exit 1; }
text
== deploy build/shop.war -> /opt/tomcat/webapps/ROOT.war
  [dry] cp /opt/tomcat/webapps/ROOT.war /opt/tomcat/backup/ROOT.war.20260910_164211
== stop tomcat
  [dry] /opt/tomcat/bin/shutdown.sh
  [dry] rm -rf /opt/tomcat/webapps/ROOT /opt/tomcat/webapps/ROOT.war
  [dry] rm -rf /opt/tomcat/work/Catalina/localhost/ROOT
  [dry] cp build/shop.war /opt/tomcat/webapps/ROOT.war
== start tomcat
  [dry] /opt/tomcat/bin/startup.sh
== health check http://localhost:8080/
== done (ROOT, backup=20260910_164211)

DRY_RUN=1 이면 run 함수가 명령을 실행하지 않고 출력만 합니다. 배포 전 이 출력으로 경로가 맞는지 확인하고, 서버에서는 DRY_RUN 없이 실행합니다.

예제 3: nginx 설정 교체 — nginx_reload.sh 발췌

bash
NEW=${1:-}
if [ -n "$NEW" ]; then
  [ -f "$TARGET" ] && cp "$TARGET" "$TARGET.bak"
  cp "$NEW" "$TARGET"
fi
if ! nginx -t; then
  echo "문법 오류, 이전 설정으로 되돌립니다"
  [ -f "$TARGET.bak" ] && cp "$TARGET.bak" "$TARGET"
  exit 1
fi
systemctl reload nginx
sleep 1
systemctl is-active --quiet nginx || { systemctl restart nginx; exit 1; }
text
== 설정 교체 bad.conf -> /etc/nginx/conf.d/myapp.conf
  [dry] cp /etc/nginx/conf.d/myapp.conf /etc/nginx/conf.d/myapp.conf.bak
  [dry] cp bad.conf /etc/nginx/conf.d/myapp.conf
== nginx -t (문법 검사)
  문법 오류, 이전 설정으로 되돌립니다
종료 코드=1

잘못된 설정을 넣으면 검사 단계에서 멈추고 .bak 으로 되돌립니다. reload 뒤 1초 후 is-active 로 살아 있는지 한 번 더 확인합니다.

예제 4: 리버스 프록시 설정 — myapp.conf

nginx
upstream myapp {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=10s;
}
server {
    listen 80;
    server_name myapp.example.com;
    access_log /var/log/nginx/myapp.access.log;
    location /static/ { root /opt/myapp/public; expires 7d; }
    location / {
        proxy_pass http://myapp;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_connect_timeout 5s;
        proxy_read_timeout 60s;
    }
}

proxy_read_timeout 은 자바 앱의 가장 긴 요청보다 길어야 504 가 안 납니다. 엑셀 다운로드처럼 오래 걸리는 경로는 별도 location 으로 빼서 값을 따로 줍니다.