[해결] 배포 시 오류 발생 - 접속 안됨

김설영·2022년 8월 6일
0

결론


spring boot 2.5.0 이상 버전에서 gradle을 사용하여 빌드를 할 경우, jar 파일이 2개 생성된다.

  • 앱이름.jar → bootJar task로 생성된 것
    • 해당 파일은 해당 프로젝트에 필요한 모든 의존성이 같이 추가된 것으로, MANIFEST.MF까지 모두 정상적인 상태로 나옴.
  • 앱이름-plain.jar → build task로 생성된 것
    • 해당 파일은 의존성을 제외하고, 딱 프로젝트에 있는 자원들만 jar로 만든 것으로, MANIFEST.MF에 Main 메소드의 위치가 나오지 않는다.

즉, 앱이름-plain.jar를 실행하는 것을 막아야 한다.

두 가지 방법이 있다.

  • build.gradle에 다음 코드 추가하여 앱이름-plain.jar의 생성 자체를 막는다.
    jar {
    	enabled = false
    }
  • linux 명령어 grep을 활용하여 앱이름-plain.jar 를 스캔 및 실행 대상에서 제외한다.
    ls -tr $REPOSITORY/*.jar | grep -v "plain" | tail -n 1

해결 과정


  • 아무래도 프로세스가 2개 실행되고 있어서 발생하는 문제인것 같다
  • sudo kill -9 {process_id} 명령어로 모두 중지시키자.
  • 다시 해본다 → 안됨
  • nohup.out 파일을 확인한다.
no main manifest attribute, in /home/ec2-user/app/step2/RestApiPractice-1.0.1-SNAPSHOT-plain.jar
  • 위 오류는 JVM이 jar 파일에서 가장 처음 실행할 Main class를 찾지 못할 때 발생하는 오류다.
  • 이에 대한 설정은 jar 파일 내부의 META-INF/MANIFEST.MF 파일에 등록되어 있어야 한다.
  • 그런데, jar 파일의 이름이 이상하다? RestApiPractice-1.0.1-SNAPSHOT-**plain**.jar

spring boot 2.5.0 이상 버전에서 gradle을 사용하여 빌드를 할 경우, jar 파일이 2개 생성된다.

  • 앱이름.jar → bootJar task로 생성된 것
    • 해당 파일은 해당 프로젝트에 필요한 모든 의존성이 같이 추가된 것으로, MANIFEST.MF까지 모두 정상적인 상태로 나옴.
  • 앱이름-plain.jar → build task로 생성된 것
    • 해당 파일은 의존성을 제외하고, 딱 프로젝트에 있는 자원들만 jar로 만든 것으로, MANIFEST.MF에 Main 메소드의 위치가 나오지 않는다.

즉, 위 에러는 앱이름-plain.jar 파일이 생성되어서 발생된 에러다.

  • 해결 (참고: https://dongjuppp.tistory.com/87)

    1. rm {파일이름} 명령어로 앱이름-plain.jar 파일을 모두 삭제한다.

      jar {
      	enabled = false
      }
    2. build.gradle 파일에 위의 명령어를 추가한다.

      • 위 명령어를 추가해주면 앱이름-plain.jar 파일이 생성되지 않는다.

👉 일단은 위의 방법으로 해결했다. 접속까지 완료!


그런데 문득, deploy.sh 파일에서, plain이 붙은 파일은 실행 대상에서 제외할 수 있지 않을까? 하는 생각이 들었다.

JAR_NAME=$(ls -tr $REPOSITORY/*.jar | tail -n 1)  # 뭔가 여기서 -plain.jar를 걸러낼 수 있을 것 같은데.. 지속적으로 알아보자.

nohup java -jar \
-Dspring.config.location=classpath:/application.yaml,/home/ec2-user/app/application-oauth.properties,/home/ec2-user/app/application-real-db.properties \
-Dspring.profile.active=real \
$JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
  • ls -tr $REPOSITORY/*.jar | tail -n 1
    • |는 파이프라고 한다. A|B → A의 표준 출력을 B의 표준 입력으로 입력받는다.
    • ls -tr $REPOSITORY/*.jar → jar 파일을 모두 출력한다.
    • | tail -n 1 → 출력한 jar 파일 중, 가장 최신의 것을 입력한다. → 입력이 곧 JAR_NAME에 저장된다.
    • ls -tr $REPOSITORY/*.jar | grep -v "plain" | tail -n 1 를 이용해서 plain이 들어간 jar 파일을 스캔 대상에서 제외해보자

👉 와 된다!!!!!!!!!!!!!

  • nohup ... $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
    • Jar 파일을 nohup으로 실행 → 실행 파일이 nohup.out에 저장됨
    • 생각해보니, 나는 > , 2>&1 등의 리눅스 명령어를 모른다. 일단 이것부터 알아보자.
    • $JAR_NAME > $REPOSITORY/nohup.out 2>&1
      • $JAR_NAME을 $REPOSITORY/nohup.out에 저장한다
        • 명령 > 파일 : 명령의 결과를 파일로 저장
        • jar 파일이 출력하는 것을 nohup.out 파일에 저장함. >가 한개이므로 덮어씀.
      • 2>&1 : 표준 에러(2)를 표준 출력(1)으로 리디렉션 한다. → 키보드 입력, 화면 출력을 사용하지 않음.
        • >& : 명령이 실행된 표준 출력의 결과와 에러를 파일로 출력
        • 이는 에러가 발생해도, 프로그램이 작동을 멈추거나 꺼지지 않게 해준다.
        • 대신, 에러내용을 표준 출력 동작으로 행동하게 한다. 또한, 화면에 경고 메시지를 출력하지 않고, 파일이나 딴 곳으로 처리하게 한다.


Reference


[Linux] nohup 세션이 끊겨도 계속 실행되도록 해보자

리눅스 표준 입출력 리다이렉션

[LINUX] 📚 /dev/null 과 2>&1 완벽 이해하기 (리다이렉션 기호 조합 정리)

[LINUX] 📚 입출력 재지정 & 파이프 명령어 💯 정리

profile
블로그 이동하였습니당! -> https://kimsy8979.tistory.com/

1개의 댓글

comment-user-thumbnail
2023년 3월 24일

감사합니다 ㅠㅠㅠ

답글 달기