使用 simple-build-tool (sbt) 和 IntelliJ 调试 Scala 代码

Posted

技术标签:

【中文标题】使用 simple-build-tool (sbt) 和 IntelliJ 调试 Scala 代码【英文标题】:Debugging Scala code with simple-build-tool (sbt) and IntelliJ 【发布时间】:2011-05-08 05:42:45 【问题描述】:

使用 IntelliJ 的内置调试器调试 sbt 管理的 Scala 代码最简单的方法是什么? "RunningSbt" from sbt's google code site 的文档列出了用于运行项目或测试的主类的命令,但似乎没有用于调试的命令。

后续问题:使用 sbt 的 jetty-run 命令时,将 IntelliJ 的调试器附加到 Jetty 的最简单方法是什么?

【问题讨论】:

【参考方案1】:

官方SBT packages 中有一个非常方便的-jvm-debug 标志,适用于Mac、Linux 和Windows。您可以使用该标志来指定调试端口:

sbt -jvm-debug 5005

Under the covers,这会使用典型的详细调试咒语启动 SBT 的 JVM:

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

您现在可以正常运行代码,例如使用 sbt run 命令。

正在配置 IntelliJ 以连接到正在运行的代码...

现在您使用 Remote Debug configuration 将 IntelliJ 连接到正在运行的进程。请注意,此表单中的前 3 个字段虽然很吓人,但仅供您将文本 out 复制,而不是复制到其中(它们给出了上面指定的详细调试咒语,-jvm-debug 已经照顾你) - 你可以更改的唯一配置是在Settings 部分中途:

【讨论】:

这在 Windows 上不起作用——知道如何在这个(糟糕的)平台上做类似的事情吗? 这是我相信用于 Windows 的启动器脚本:github.com/sbt/sbt-launcher-package/blob/master/src/windows/sbt。我鼓励您弄清楚如何修改脚本以接受 -jvm-debug 参数,并将其作为拉取请求提交 - 您很有可能使发现自己在同一平台上的每个人受益。 拉取请求merged...见below 知道在 IntelliJ 中插入“sbt -jvm 5005”的位置会很有帮助 效果很好。请注意,在最新的 IntelliJ 版本中,我们没有获得这 3 个选项 - 所以您只需按下应用按钮并开始调试(虽然这是针对 Mac 版本)【参考方案2】:

对于 IntelliJ 中的普通调试,您可以以通常的方式使用应用程序运行/调试配置,无论您是否使用 sbt 编译代码。

要连接到在 Jetty 中运行的应用程序,您需要创建远程调试配置。当您这样做时,IntelliJ 将为您提供一组用于运行远程 JVM 的命令行参数——类似于

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

使用这些参数启动 sbt,然后执行 jetty-run。最后,在 IntelliJ 中启动远程调试配置。 This thread 可能有用。

【讨论】:

对我来说以通常的方式效果不佳:***.com/questions/16337745/… 你在哪里输入这个? -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 @Jwan622 使用这些参数启动 sbt(例如,从命令行,将这些作为命令行参数提供)。然后在 sbt 提示符下执行jetty-run 那么就运行sbt -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 ? 对于大多数用户来说应该可以工作,但这取决于你的系统上 sbt 的设置方式。如另一个答案中所述,您可能只需运行sbt -jvm-debug 5005【参考方案3】:

我也遇到了一些麻烦,所以冒着过于详细的风险,这就是我所做的:

设置

    为 sbt jetty-run 创建运行配置

    转至运行 > 编辑配置 单击 [+] 图标并选择 Scala 编译服务器 输入您想要的任何名称,然后单击“Run SBT Action”复选框并从 [...] 中选择 SBT Action jetty-run

    为远程调试创建调试配置

    转至运行 > 编辑配置 单击 [+] 图标并选择远程 输入您想要的任何名称并复制行-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005(确保单击“确定”以实际创建配置)

    设置 sbt 插件以运行上面的 vm 选项

    转到文件 > 设置 > SBT 在 VM 参数框中粘贴 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 行,在已经存在的参数之后

调试

    根据需要设置断点 通过选择您在上面创建的 sbt jetty-run 配置并选择 Run > Run 或单击绿色箭头来启动 jetty Web 服务器 通过选择您在上面创建的远程调试配置并选择“运行”>“调试”或单击错误图标来启动远程调试器

【讨论】:

配置菜单中没有 Scala 编译服务器。所以我需要一些特别的东西吗? 似乎不需要step1,我要做的是运行sbt命令sbt -jvm-debug 5005 console,然后在intellJ Idea中设置断点,运行调试。 @Pengfei.X, sbt -jvm-debug 5005 console 对我不起作用,但 sbt -jvm-debug 5005 对我有用。【参考方案4】:

这个每次都对我有用,你唯一需要设置的是在 IntelliJ 中进行远程调试;我从 IntelliJ 的终端使用 JVM 参数启动 SBT:

sbt -J-Xdebug -J-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

之后我可以在 localhost:5005 上开始远程调试

【讨论】:

【参考方案5】:

这些答案或提供的链接都不适合我,所以一旦我弄清楚了,我想我会分享...

包括我刚开始时所没有的背景知识……

这主要基于here 的说明,只是附带了一些帮助我完成它的额外解释。

我的环境: Scala 2.10.2、SBT 0.13 和 IntelliJ 13.1

背景:

无论出于何种原因,在 IntelliJ 中使用 SBT 编译 Scala 并没有像 Maven 项目那样集成(这使得调试非常容易)。 据我了解,使用 SBT 编译时,您是在单独的进程中编译,因此,您需要进行远程调试。

什么是调试?

调试是一种运行 JVM 或应用程序的模式,可让您控制代码执行流程。 然后,您使用的调试工具可以向调试引擎发出命令,告诉它“执行下一行代码然后再次暂停”或“继续执行”或“获取存储在内存中的变量的值”。

什么是远程调试?

远程调试是通过网络连接(套接字)进行调试。 此网络连接允许您从远程计算机向调试引擎发出命令。 当您想要调试在远程服务器上运行的代码时,这很有用,但是 对于在 SBT 下运行的 Scala 代码并通过独立于 IntelliJ 环境的 Web 服务器(例如 Jetty 或 Tomcat)启动等情况,它也很有用。

参考上面的链接,下面的解释/修改很有用:

    设置 IntelliJ 以使用“启用调试”JVM 设置启动 SBT,包括设置网络套接字时使用的端口。 (未更改)将命名的 VM 参数添加到您的 IntelliJ 设置中。 确保此处的端口号与步骤 1 中的 JVM 设置相匹配。 当您启动 SBT 时,您需要从 SBT 控制台插件(这是您在步骤 1 中配置的)执行此操作。如果您在 IntelliJ 之外(在命令行)运行 SBT,则需要使用与步骤 1 中相同的 VM 参数启动 SBT(我没有这样做;所以没有说明)。在这一步之后,SBT 现在正在运行(但您的代码还没有),并且 JVM 已设置为远程调试。 这会启动 IntelliJ 调试工具,该工具会连接到您在第 3 步中启动的 JVM。 最后,您在 SBT 控制台中开始编译。您可以使用任何编译命令执行此操作,包括连续编译命令。如果连续重新编译,将发生重新编译,但不会在代码执行被调试器暂停时发生。

【讨论】:

链接已损坏。【参考方案6】:

我在这里添加另一个答案,因为我在查找相关问题时发现了这个问题:使用断点调试测试类。

我正在使用 ScalaTest,我通常使用 sbt 的“仅测试”命令运行一个套件。现在,当我想使用交互式调试器时,我可以执行以下操作:

创建一个“ScalaTest”类型的新运行/调试配置,输入主“测试类:”名称,然后选择“启动前:运行 SBT 操作 'test-compile'”。就是这样,您现在可以在测试源中放置断点,然后运行此配置。

【讨论】:

相同,但效果不佳:***.com/questions/16337745/… 如果测试类有多个测试,你知道我如何只运行一个测试吗?请看下面的问题***.com/questions/54977741/…【参考方案7】:

我也一直在努力在 Windows 上使用 Intellij 通过 SBT 构建的 Spray-can / Akka / Scala 应用程序进行调试。综合各种建议,对我来说最简单的方法是:

    确保您的项目/plugsin.sbt 文件中有 sbt.Revolver,例如

    addSbtPlugin("io.spray" % "sbt-revolver" % "0.7.1")

    在 build.sbt 文件中设置 javaoptions:

    javaOptions := Seq("-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005")

特别是使用suspend=y 选项。这将保留应用程序,直到您从 Intellij 连接远程调试器

    通过运行/编辑配置菜单在 Intellij 中设置调试器配置。按+按钮,选择“远程”选项。确保条目与上面的 javaoptions 匹配,特别是 5005 的端口地址。为配置命名,如“Spray”。

    从您的 SBT 控制台使用重新启动命令。您应该会在反馈输出中看到 5005 端口地址。

    在 Intellij 中设置断点。

    在 Intellij 中,选择 Run \ Debug 'Spray'。这应该连接到喷雾罐网络服务器。您应该能够在调试窗口中看到很多线程。

    请注意,Spray 中的某些 Get 指令似乎会在启动时执行,但不会在调用网站时重复执行。

【讨论】:

【参考方案8】:

对于 Windows 用户的价值,编辑 %SBT_HOME%\bin\sbt.bat 并找到以下代码行:

:run

"%_JAVACMD%" %_JAVA_OPTS% %SBT_OPTS% -cp "%SBT_HOME%sbt-launch.jar" xsbt.boot.Boot %*
if ERRORLEVEL 1 goto error
goto end

然后用以下代码替换它们:

FOR %%a IN (%*) DO (
  if "%%a" == "-jvm-debug" (
    set JVM_DEBUG=true
    set /a JVM_DEBUG_PORT=5005 2>nul >nul
  ) else if "!JVM_DEBUG!" == "true" (
    set /a JVM_DEBUG_PORT=%%a 2>nul >nul
    if not "%%a" == "!JVM_DEBUG_PORT!" (
      set SBT_ARGS=!SBT_ARGS! %%a
    )
  ) else (
    set SBT_ARGS=!SBT_ARGS! %%a
  )
)

if defined JVM_DEBUG_PORT (
  set _JAVA_OPTS=!_JAVA_OPTS! -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=!JVM_DEBUG_PORT!
)

call :run %SBT_ARGS%

if ERRORLEVEL 1 goto error
goto end

:run
"%_JAVACMD%" %_JAVA_OPTS% %SBT_OPTS% -cp "%SBT_HOME%sbt-launch.jar" xsbt.boot.Boot %*
goto :eof

当在 Bash 脚本启动器中看到 -jvm-debug 时,我能做的最好的事情是获得相同的行为

注意。我不认为%SBT_HOME% 实际上存在于这个脚本之外,除非你在你的环境中明确创建,但无论如何你明白了:D

【讨论】:

拉取请求merged【参考方案9】:

文件->设置->其他设置->SBT 虚拟机参数 -Xmx512M -XX:MaxPermSize=256M -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

运行->编辑配置 按 + 然后选择远程 按应用

现在在 SBT 控制台(由 intelliJ 内部启动)中,当您执行命令 'run' 时,您将看到“Listening for transport dt_socket at address: 5005”

现在按运行->调试。您将看到下面激活的调试菜单。它有两个选项卡调试器和控制台。

使用 F7 从下一行到下一行

我选择了暂停作为 n。当我运行运行命令时它是 y,它被卡住了

【讨论】:

【参考方案10】:
export SBT_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5009

试试这个

【讨论】:

【参考方案11】:

AttachMe IntelliJ 插件可能会更快地连接调试器,而无需摆弄端口号:

AttachMe 会自动附加 IntelliJ 调试器,即使您 从终端(或任何其他方式)启动您的应用程序。你不需要 手动触发Attach to process 动作。

Blog post 和 readme 有设置说明,但是我必须稍微修改一下才能让它在我的机器上运行

    从官方仓库下载installer.sh脚本

    curl -o installer.shhttps://raw.githubusercontent.com/JetBrains/attachme/master/installer.sh
    
    给它可执行权限chmod u+x installer.sh 使用./installer.sh 运行它 这应该在/.config/attachme/agent.jar下安装代理并创建~/.attachme文件

    修改~/.attachme以包含

    AM_JDWP_ARGS="transport=dt_socket,server=y,suspend=y,address=127.0.0.1:0"
    echo Using JDWP arguments $AM_JDWP_ARGS
    export JAVA_TOOL_OPTIONS="- javaagent:/Users/mario_galic/.config/attachme/agent.jar -agentlib:jdwp=$AM_JDWP_ARGS"
    echo "AttachMe configured successfully"
    

    安装对应的Attachme插件并重启:IntelliJ | Preferences | Plugins

    创建Attachme运行配置:Run | Edit configurations... | Add new configuration | Attachme debugger registry | OK

在这些一次性的恶作剧之后,我们可以通过以下方式自动附加一个调试器

    开始Attachme运行配置 source ~/.attachme 从终端启动应用程序,可能是sbt "runMain example.Hello" 调试器应自动附加并在任何断点处停止

【讨论】:

【参考方案12】:

我也遇到了同样的问题,我想分享一下我是如何解决的。顺便说一句,我使用的是 Ubuntu 14.04 和 IntelliJ 15。

    在设置中 -> SBT -> 粘贴在 VM 参数文本框中的下一行:

    -XX:MaxPermSize=384M -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005

    在 IntelliJ 中打开 Termilal 并运行:

    sbt -jvm-debug 5005

    注意:您应该在终端中看到这一行:“Listening for transport dt_socket at address: 5005”

    编辑配置 -> 点击 + -> 选择“远程”

    I. Give some name example: DebugMyModule
    
    II. All needed configurations will be set automatically, But you just verify. In Command line arguments should look like this "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005".
    
    III. In 'Search Sources in Module's Classpath' text box specify your module in which module your test cases are there.
    
    IV. put 127.0.0.1 host instead of 'localhost'. 'localhost' not working for me.
    

    Edit Configurations列表框中选择DebugMyModule,然后点击Debug

    注意:您应该会看到 Debug View 打开并在 Debug Console 中您应该能够看到“已连接到目标 VM,地址:'127.0.0.1:5005',传输:'socket'”

    在 Testclass 的几个测试用例中放置断点。

    来到你运行“sbt -jvm-debug 5005”的终端并像下面这样运行

    project <your-module-name>
    it:testOnly package.TestSpec
    

    例如:com.myproject.module.AddServiceTest[Spec]

    您可以在测试用例断点中看到调试开始。

【讨论】:

不适用于 Ubuntu 16.04 和 IntelliJ 2017.3,调试器附加但断点被忽略。 testSuite 不能在断点处停止,但是如果断点在 main 方法中,它可以。【参考方案13】:

关于一个相对较新的 Intellij 版本(2020.1.4)一步一步给分:

配置 Intellij

“编辑配置” 添加“远程” 这个新版本的 Intellij 不允许您在“命令行参数”中编辑字符串,您只能编辑上面的“主机”和“端口”,我将其保留为默认值;我只将下面的“模块路径”更改为“root”(不确定是否有必要)

远程调试

设置断点 在命令行中执行sbt命令,例如sbt -jvm-debug 5005 test 立即回到 Intellij 并点击“Debug”,它应该会显示类似“Connected to xxx”的信息,然后等到它在断点处暂停

【讨论】:

谢谢!这个解决方案效果很好!我只是运行“sbt -jvm-debug 5005 run”。【参考方案14】:

按照上面 Roberto Tyley 的回答,但是在 Windows 中我们还需要在安装 sbt 后设置以下环境变量:

SBT_HOME C:\Program Files (x86)\sbt\[或安装 sbt 的地方]

SBT_OPTS -Xdebug -runjdwp:transport=dt_socket,server=y,suspend=n,address=5005

[根据 RT 的 IntelliJ 示例]

添加到路径:%SBT_HOME%\bin;%SBT_OPTS%

然后在项目文件夹内的命令行中运行以下 “sbt 运行 -jvm -debug 5005”。

如果这工作正常,命令行最初会输出一行 re "侦听地址为 5005 的传输 dt_socket"。

在 IntelliJ 中设置断点。

在浏览器中打开网站以触发调试器断点,例如“http://localhost:9000/”。

【讨论】:

以上是关于使用 simple-build-tool (sbt) 和 IntelliJ 调试 Scala 代码的主要内容,如果未能解决你的问题,请参考以下文章

在“sbt-native-packager”脚本中使用除“sbt run”之外的其他 sbt 命令。例如:“sbt flywayMigrate”

如何在 sbt-plugin 中使用 sbt-assembly?

如何在 sbt 项目中使用 sbt 插件作为库依赖项?

有人可以解释使用 SBT 的正确方法吗?

使用 sbt-native-packager 为我的 sbt 项目获取 docker 支持时出错

使用 sbt-spark-package 插件了解 build.sbt