Debugging 从IntelliJ调试Grails应用程序

Debugging 从IntelliJ调试Grails应用程序,debugging,grails,intellij-idea,Debugging,Grails,Intellij Idea,我一直在努力从IntelliJ内部调试Grails2.5.0应用程序。具体来说,我发现很难将应用程序配置为 功能测试可以调试 可以运行功能测试 该应用程序可以调试 该应用程序可以运行 当(1)和(2)从IntelliJ内部启动时(版本14.1.4) 这是我用来调查这个问题的一个例子,它有一个单一的功能测试。使调试工作正常的关键似乎是这些JVM分叉设置 调试运行应用程序(3) 启用分叉功能后,可以通过从IntelliJ内部运行应用程序,然后从IDE启动远程调试器以连接到端口5005上的应用程序来调

我一直在努力从IntelliJ内部调试Grails2.5.0应用程序。具体来说,我发现很难将应用程序配置为

  • 功能测试可以调试
  • 可以运行功能测试
  • 该应用程序可以调试
  • 该应用程序可以运行
  • 当(1)和(2)从IntelliJ内部启动时(版本14.1.4)

    这是我用来调查这个问题的一个例子,它有一个单一的功能测试。使调试工作正常的关键似乎是这些JVM分叉设置

    调试运行应用程序(3) 启用分叉功能后,可以通过从IntelliJ内部运行应用程序,然后从IDE启动远程调试器以连接到端口5005上的应用程序来调试该应用程序。JVM分叉设置确保应用程序始终在启用远程调试的情况下运行,因此请确保通过运行而不是调试来启动应用程序

    调试功能测试(1) 要调试功能测试,您需要包括

    这样可以禁用分叉(和远程调试)。然后,您可以通过IntelliJ调试配置启动测试来调试功能测试

    根据正在调试的是应用程序还是功能测试,必须包含/注释这一行是相当乏味的,因此我正在寻找一个更简单的解决方案

    有人可能会认为这是可以避免的

    if (Environment.current == Environment.TEST) {
        grails.project.fork = null
    }
    

    但是由于一些未知的原因,这不起作用。

    我在
    BuildConfig.groovy
    中有以下设置:

    grails.project.fork = [
    
        // configure settings for the test-app JVM, uses the daemon by default
        test: false, // see http://youtrack.jetbrains.com/issue/IDEA-115097
        // configure settings for the run-app JVM
        run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
        // configure settings for the run-war JVM
        war: false,
        // configure settings for the Console UI JVM
        console: false
    ]
    
    您需要在intellij中添加2个运行配置:

    • 为grails项目添加新的运行配置。使用
      runapp--debug fork
      作为命令行
    • 添加新的远程调试配置。只需使用默认设置
    要调试应用程序,请运行第一个配置。grails应用程序将启动,并应打印地址为5005的侦听传输dt_套接字的
    。一旦看到此消息,请运行调试配置

    如果您需要屏幕截图,请告诉我。启动远程调试时,无需等待“侦听地址为5005的传输dt_套接字”行。只需运行远程调试并运行应用程序

    简言之:

    BuildConfig.groovy

    // jvmArgs make it so that we can run in forked mode without having to use the `--debug-fork` flag
    // and also has suspend=n so that it will start up without forcing you  to connect a remote debugger first
    def jvmArgs = ['-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005']
    
    grails.project.fork = [
    test: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256,     daemon:true, jvmArgs: jvmArgs],
        run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false, jvmArgs: jvmArgs],
        war: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false, jvmArgs: jvmArgs],
        console: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, jvmArgs: jvmArgs]
    ]
    
    在启动远程调试器之前监视端口

    如果在intellij中创建新的远程调试目标并在 在运行应用程序或测试的同时,它将失败,因为调试失败 端口尚未打开。如果手动打开,则需要等待 显示调试端口已打开的日志消息。更多信息 我们可以通过一个小把戏来避免照看孩子

    下面是一个shell脚本,它使用nc(netcat)命令监视 localhost端口,并且仅在端口可用时才继续。 将其保存为路径中的某处wait_for_port.sh:

    让它将此脚本用作监视端口5005的“外部工具” 在它尝试连接之前


    要调试应用程序本身,从
    grails3
    开始,我们可以转到
    Grails-app/init
    ,然后右键单击
    Application.groovy
    类并单击
    Debug'Application'

    grails.project.fork = [
    
        // configure settings for the test-app JVM, uses the daemon by default
        test: false, // see http://youtrack.jetbrains.com/issue/IDEA-115097
        // configure settings for the run-app JVM
        run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
        // configure settings for the run-war JVM
        war: false,
        // configure settings for the Console UI JVM
        console: false
    ]
    
    // jvmArgs make it so that we can run in forked mode without having to use the `--debug-fork` flag
    // and also has suspend=n so that it will start up without forcing you  to connect a remote debugger first
    def jvmArgs = ['-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005']
    
    grails.project.fork = [
    test: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256,     daemon:true, jvmArgs: jvmArgs],
        run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false, jvmArgs: jvmArgs],
        war: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false, jvmArgs: jvmArgs],
        console: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, jvmArgs: jvmArgs]
    ]
    
    #!/usr/bin/env bash
    PORT_NUMBER="$1"
    
    function usage {
        echo "usage: ${0##*/} "
        echo "ex: ${0##*/} 5005"
    }
    
    if [ -z $PORT_NUMBER ]; then
        usage
        exit 1
    fi
    
    echo "waiting for port $PORT_NUMBER to open up"
    
    while ! nc -z localhost $PORT_NUMBER; do sleep 0.1; done;