programing

봄 부츠와 그라들이 있는 CTRL+C는 그라들 데몬을 죽인다.

starjava 2023. 7. 21. 20:26
반응형

봄 부츠와 그라들이 있는 CTRL+C는 그라들 데몬을 죽인다.

저는 스프링 부트 그래들 플러그인을 사용하여 Tomcat 서버와 제 앱을 시작합니다.를 다을통해 Tomcat다작니합을 통해 합니다.gradle bootRun또한 Gradle 데몬을 활성화하여 Gradle 빌드를 더 빠르게 진행할 수 있도록 했습니다.

그러나 데몬을 활성화해도 소용이 없습니다.+를 통해 서버를 중지할 때마다 서버를 다시 시작합니다.gradle bootRun다음 메시지가 나타납니다.

Starting a new Gradle Daemon for this build (subsequent builds will be faster).

Ctrl SpringC Boot의 표지 아래 Tomcat 서버를 중지시킬 뿐만 아니라 Gradle 데몬도 죽입니다.그래들의 데몬 모드의 목적을 저버리는 거지

함께 tomcat을 시작한 것과 같은 터미널의 명령줄 인터페이스를 통해 서버를 중지해야 하는 더 좋은 방법이 요?gradle bootRun그래들 데몬을 살려둘 수 있을까요

이것은 Gradle 4에서 여전히 이슈입니다.나의 최선의 타협/해결책(charlie_pl의 답변 구축):

  1. 를 누릅니다.ctrl+z실행 중인 프로세스를 백그라운드로 전송합니다.
  2. 다음과 같이 프로세스를 종료합니다.kill $(ps aux | grep "MyApp" | grep -v grep | awk '{print $2}')
  3. 시작: 다시시:./gradlew run ...

저는 스프링 부트 플러그인에 대해 잘 모르기 때문에 (제티 플러그인에 있는 것처럼) 'bootStop' 명령은 없을 것입니다.또한 광범위한 검색을 해보니 원하는 결과에 대한 명령줄 옵션이 없는 것 같습니다.

한 가지 방법은 분명히 슬러지이지만 Tooling API를 사용하는 것입니다. (전체 코드 예제는 여기에 있습니다.)

이 아이디어는 Groovy 스크립트에서 장기간 실행되는 작업을 시작하는 것입니다.시 하고 " 명시스트가작중을호고다지니출합하업령"를 호출합니다.gradle tasks데몬을 간지럽히기 위해.

위에 링크된 GitHub 코드에서 장시간 실행되는 작업은 다음과 같습니다.

task runService() << {
    ant.delete(file: "runService.log")
    def count = 0
    while(true) {
        new File("runService.log").withWriterAppend {
            it.writeLine("[runService] count: ${count}")
        }
        println "sleeping ...."
        try { Thread.sleep(5 * 1000) } catch (Exception ex) {}
        count++
    }
}

Groovy 스크립트 뒤에 있는 아이디어는 백그라운드 스레드에서 작업을 시작한 다음 명령을 수신하면 취소 토큰을 보내는 것입니다.

명확한 설명을 위해 두 섹션을 설명하겠습니다.첫 번째 섹션은 백그라운드 스레드입니다.

class BuildRunner implements Runnable {
    def connector
    def tokenSource
    def taskName

    BuildRunner(connector, tokenSource, taskName) {
        this.connector = connector
        this.tokenSource = tokenSource
        this.taskName = taskName
    }

    public void run() {
        def connection = connector.connect()        
        try {            
            def build = connection.newBuild()
            build.withCancellationToken(tokenSource.token())
            build.setStandardOutput(System.out)
            build.setStandardError(System.err)
            build.forTasks(taskName)
            build.run()
            println "${taskName} is finishing ..."
        } catch(BuildCancelledException bcex) {
            println "received cancel signal"
            println "tickling daemon ..."
            tickleDaemon(connector)
            println "Done."
            System.exit(0)
        } catch(Exception ex) {
            println "caught exception : " + ex
        } finally {            
          connection.close()        
        }        
    }

    def tickleDaemon = { connector ->
        final String TASKS = "tasks"
        def connection = connector.connect()        
        def build = connection.newBuild()
        build.forTasks(TASKS)
        build.run()
    }
}

다른 섹션은 기본 콘솔입니다.

// main -----------

// edit as appropriate
final String TASK_NAME = "runService"
final String GRADLE_INSTALL_DIR = "/Users/measter/tools/gradle-2.14.1"
final String PROJECT_DIR = "../service"

def connector = GradleConnector.newConnector()
connector.useInstallation(new File(GRADLE_INSTALL_DIR))
connector.forProjectDirectory(new File(PROJECT_DIR))

def tokenSource = connector.newCancellationTokenSource()

println "starting ${TASK_NAME}"
def buildRunner = new BuildRunner(connector, tokenSource, TASK_NAME)
new Thread(buildRunner).start()

def console = new Scanner(System.in)
println "Enter a command (S: stop task, Q: quit): "

while (console.hasNextLine()) {
    def lineTokenizer = new Scanner(console.nextLine())
    String token = lineTokenizer.next()
    if (token.equalsIgnoreCase("S")) {
        tokenSource.cancel()
    } else if (token.equalsIgnoreCase("Q")) {
        println "Done."
        System.exit(0)
    }
}

이 코드는 다른 작업을 실행하거나 작업을 다시 시작하기 위해 쉽게 사용자 지정할 수 있습니다.그것은 개인적인 명령줄 사용에 대한 미화된 포장지를 암시합니다.

여기 +가 데몬을 죽이는 이유에 대한 코어 개발자의 설명이 있습니다.

그것은 항상 "의도적으로" 이런 식이었지만, 우리는 데몬이 그렇게 자주 죽지 않도록 그것에서 벗어나고 싶습니다.ctrl+c를 전파하지 않는 경우가 있다고 생각합니다만, 그것은 운에 의한 것입니다.

2.5에서 연속 모드로 하는 것을 보면 데몬을 죽이지 않고 Gradle 프로세스를 종료하기 위해 ctrl+d를 추가하고 있습니다.동일한 메커니즘(ctrl+d)을 사용하는 Play 애플리케이션 지원(playRun)에서 bootRun과 유사한 문제가 발생했습니다.최종적으로 이와 같은 작업을 일반적으로 수행할 것으로 생각되지만 항상 입력을 캡처하기 전에 기존 빌드 스크립트가 stdin을 읽을 수 있는 대체 방법을 제공해야 합니다.

스털링 그린(그라들 코어 개발)

이 문제는 3.1 https://docs.gradle.org/current/release-notes#more-resilient-daemon 에서 해결된 것으로 보입니다.

bootRun의 편리한 기능입니다. 이 기능을 사용하면 하나의 명령에서 두 단계를 수행할 수 있으며, 이 기능을 사용할 경우 생성되지 않는 매우 작은 이점이 있습니다..jar파일을 생성합니다.또한 잠재적으로 큰 이점이 있습니다.

개발 도구가 프로젝트에 추가된 경우 응용 프로그램에서 변경 사항을 자동으로 모니터링합니다.

의 라이브 업데이트 기능을 사용하지 않는 경우bootRun"응용 프로그램 실행"에서 설명한 대로 빌드/실행 시퀀스를 두 개의 명령으로 수행하여 이 문제를 해결할 수 있습니다.두 번째 명령은 Gradle을 포함하지 않으므로 이제 사용할 수 있습니다.Ctrl-CGradle을 남겨두는 단점이 없는 서버CANCELED주.

다음은 이러한 접근 방식을 적용하는 예입니다.

gradle build && java -jar build/libs/myproject-0.0.1-SNAPSHOT.jar

반면에 devtools사용하는 경우 서버를 수동으로 자주 다시 시작할 필요가 없을 수도 있습니다. 다시 시작하면 서버가 자동으로 다시 시작됩니다(Groovy의 경우 원본 파일만 업데이트하면 됩니다).

spring-boot-dev 도구를 사용하는 응용 프로그램은 클래스 경로의 파일이 변경될 때마다 자동으로 다시 시작됩니다.

./gradlew build -x test

...IDE(예: 'vscode')를 사용하는 경우 자동으로 Java 파일을 컴파일할 수 있으므로 Java 파일을 저장하기만 하면 서버를 간접적으로 다시 시작할 수 있습니다.그런 다음 Java는 이 점에서 Groovy만큼 원활해집니다.

저도 같은 문제가 있었습니다.저는 드롭위저드 애플리케이션을 시작했고, 데몬을 죽이면 애플리케이션을 다시 시작하는 데 걸리는 시간이 상당히 길어졌습니다.

간편한 솔루션:결국 저는 단순히 드롭위저드 프로세스를 검색하고 명령줄(단순 킬 & ps aux & grep 조합)에서 그것을 죽였습니다.이렇게 하면 앱이 닫히고 빌드가 실패하지만 데몬은 보존됩니다.

언급URL : https://stackoverflow.com/questions/39123416/ctrlc-w-spring-boot-gradle-kills-gradle-daemon

반응형