#!/usr/bin/env python3 """직접 배포 스크립트 - Spring Boot JAR + React 정적 파일""" import paramiko, time, sys, os, io, zipfile HOST = '101.79.17.164' USER = 'root' PASS = '1q2w3e!Q' LOCAL_JAR = 'C:/GUARDiA/workspace/zioinfo-web/backend/target/zioinfo-web-1.0.0.jar' LOCAL_STATIC = 'C:/GUARDiA/workspace/zioinfo-web/backend/src/main/resources/static' client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(HOST, username=USER, password=PASS, timeout=15) sftp = client.open_sftp() def run(label, cmd, timeout=90): print(f'\n[{label}]') chan = client.get_transport().open_session() chan.set_combine_stderr(True) chan.exec_command(cmd) start = time.time() while not chan.exit_status_ready(): if chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)) sys.stdout.flush() if time.time() - start > timeout: print('[TIMEOUT]') break time.sleep(0.2) while chan.recv_ready(): sys.stdout.buffer.write(chan.recv(4096)) sys.stdout.flush() rc = chan.recv_exit_status() print(f'exit={rc}') return rc # 1. 디렉터리 준비 run('디렉터리 준비', 'mkdir -p /opt/zioinfo/app /var/www/zioinfo /var/log/zioinfo && ' 'chown -R jenkins:jenkins /opt/zioinfo /var/www/zioinfo /var/log/zioinfo && echo ok') # 2. JAR 업로드 print('\n[JAR 업로드 중...]') sftp.put(LOCAL_JAR, '/opt/zioinfo/app/app.jar') size_mb = os.path.getsize(LOCAL_JAR) // 1024 // 1024 print(f'JAR 업로드 완료: {size_mb}MB') # 3. 정적 파일 zip 후 업로드 print('\n[정적 파일 패키징 중...]') zip_buf = io.BytesIO() count = 0 with zipfile.ZipFile(zip_buf, 'w', zipfile.ZIP_DEFLATED) as zf: for root, dirs, files in os.walk(LOCAL_STATIC): rel = os.path.relpath(root, LOCAL_STATIC).replace('\\', '/') for fname in files: arc = fname if rel == '.' else f'{rel}/{fname}' zf.write(os.path.join(root, fname), arc) count += 1 zip_buf.seek(0) with sftp.open('/tmp/static.zip', 'wb') as f: f.write(zip_buf.read()) print(f'{count}개 정적 파일 업로드') # 4. 정적 파일 배포 run('정적 파일 배포', 'cd /var/www/zioinfo && unzip -q -o /tmp/static.zip && echo deployed && ls | head -5') # 5. Spring Boot 서비스 시작 run('Spring Boot 기동', 'systemctl restart zioinfo && sleep 8 && systemctl is-active zioinfo && ' 'journalctl -u zioinfo -n 8 --no-pager') # 6. API 헬스체크 run('API 헬스체크', 'curl -s -o /dev/null -w "HTTP %{http_code}" http://localhost:8080/api/company && echo " OK"') sftp.close() client.close() print('\n배포 완료!')