使用 SSH 调试 Linux 上的 .NET Core,方法是附加到进程

从 Visual Studio 2017 开始,您可以通过 SSH(安全外壳)附加到运行在本地或远程 Linux 部署上的 .NET Core 和 .NET 5+ 的进程。 本文介绍如何设置调试以及如何进行调试。 有关使用 Docker 容器调试方案,请参阅 “附加到 Docker 容器上运行的进程 ”和 容器工具 文章。 若要从 Visual Studio 调试 WSL 2 上的 Linux(不附加到进程),请参阅 使用 Visual Studio 在 WSL 2 中调试 .NET Core 应用

注释

若要调试在 Azure Kubernetes 服务(AKS)上运行的 Linux,建议使用 Bridge to Kubernetes 而不是附加到进程。

先决条件

  • 在 Linux 服务器上,需要安装 SSH 服务器,使用 curl 或 wget 解压缩并安装。 例如,在 Ubuntu 上,可以通过运行:

    sudo apt-get install openssh-server unzip curl
    

    必须启用 SFTP 以及 SSH。 大多数 SSH 分发默认安装并启用 SFTP,但情况并不总是如此。

  • 在 Linux 服务器上, 在 Linux 上安装 .NET 运行时,并查找与 Linux 分发版(如 Ubuntu)匹配的页面。 不需要 .NET SDK。

    若要确保所需的 .NET 调试服务可用于调试,请避免将应用程序发布为单文件可执行文件。

  • 有关全面的 ASP.NET Core 说明,请参阅 使用 Nginx 托管 Linux 上的 ASP.NET Core使用 Apache 托管 Linux 上的 ASP.NET Core

准备应用程序进行调试

在构建应用程序时,建议使用调试配置。 调试发布版本的代码(发布配置)比调试调试版本的代码更难。 如果需要使用发布配置,请先禁用“仅我的代码”功能。 打开“工具>选项”窗格,然后展开“所有设置>>”部分。 清除 “仅启用我的代码 ”复选框。

在构建应用程序时,建议使用调试配置。 调试发布版本的代码(发布配置)比调试调试版本的代码更难。 如果需要使用发布配置,请先禁用“仅我的代码”功能。 打开 “工具>选项 ”对话框,然后展开 “调试>常规 ”部分。 清除 “仅启用我的代码 ”复选框。

确保项目配置为生成 可移植 PDB (这是默认设置),并确保 PDB 与 DLL 位于同一位置。 若要在 Visual Studio 中配置此项,请右键单击项目,然后选择 “属性>常规>调试”符号

确保项目配置为生成 可移植 PDB (这是默认设置),并确保 PDB 与 DLL 位于同一位置。 若要在 Visual Studio 中配置此功能,请右键单击该项目,然后选择 “属性>生成>高级>调试信息”。

生成和部署应用程序

在开始调试之前,可以使用多种方法部署应用。 例如,你能够:

  • 将源复制到目标计算机,然后在 Linux 机器上使用 dotnet build 进行构建。

  • 在 Windows 上生成应用,然后将生成项目传输到 Linux 计算机。 (生成项目由应用程序本身、可移植 PDB、它可能依赖的任何运行时库以及 .deps.json 文件组成。

部署应用后,启动应用程序。

附加调试器

当应用程序在 Linux 计算机上运行时,即可附加调试器。

  1. 在 Visual Studio 中,选择 “调试>附加到进程...”

  2. “连接类型” 列表中,选择 “SSH”。

  3. 连接目标 更改为目标计算机的 IP 地址或主机名。

    如果尚未提供凭据,系统会提示输入密码和/或私钥文件。 有关使用私钥文件的详细信息,请参阅 设置远程连接

    除了 SSH 服务器正在运行的端口外,没有配置端口要求。

  4. 查找要调试的进程。

    代码在唯一的进程名称或名为 dotnet 的进程中运行。 若要查找感兴趣的进程,请检查 “标题 ”列,其中显示了进程的命令行参数。

    在以下示例中,通过 SSH 传输连接到远程 Linux 计算机并查看进程列表,该列表显示在“附加到进程”对话框中。

    附加到 Linux 进程的屏幕截图。

    附加到 Linux 进程的屏幕截图。

  5. 选择 附加

    在出现的对话框中,选择要调试的代码类型。 选择 Managed (.NET Core for Unix)

  6. 使用 Visual Studio 调试功能调试应用。

    在以下示例中,可以看到 Visual Studio 调试器在远程 Linux 计算机上运行的代码中的断点处停止。

    命中断点的屏幕截图。

    命中断点的屏幕截图。