排查与 Linux 上缺少文件相关的 .NET 错误

尝试使用 Linux 上的 .NET 时,诸如 dotnet newdotnet run 之类的命令可能会失败,并显示与找不到某项文件相关的消息,例如 fxrlibhostfxr.soFrameworkList.xml。 某些错误消息可能如下所示:

  • System.IO.FileNotFoundException

    System.IO.FileNotFoundException: 找不到文件“/usr/share/dotnet/packs/Microsoft.NETCore.App.Ref/5.0.0/data/FrameworkList.xml”。

  • 出现错误。

    出现错误。 找不到所需的 libhostfxr.so 库。

    出现错误。 文件夹 [/usr/share/dotnet/host/fxr] 不存在。

    出现错误,文件夹 [/usr/share/dotnet/host/fxr] 不包含任何以版本编号的子文件夹。

  • 找不到有关 dotnet 的一般消息

    可能会出现一条一般消息,指示找不到 SDK 或已安装包。

这些问题都有一个症状,即,/usr/lib64/dotnet/usr/share/dotnet 文件夹都在你的系统上。

提示

使用 dotnet --info 命令列出安装了哪些 SDK 和运行时。 有关详细信息,请参阅如何检查是否已安装 .NET

这是怎么回事

重要

从 .NET 9(目前为预览版)开始,Microsoft仅发布不发布自己的包的受支持 Linux 分发版的包。 有关详细信息,请参阅在 Linux 上安装 .NET

当两个 Linux 包存储库提供 .NET 包时,通常会发生这些错误。 Microsoft 提供一个 Linux 包存储库来获取 .NET 包的源代码,而某些 Linux 发行版也提供 .NET 包。 这些分发版包括:

  • Alpine Linux
  • Arch
  • CentOS 流
  • Fedora
  • RHEL
  • Ubuntu 22.04+

如果混合两种来源的 .NET 包,可能会遇到问题。 这些包可能会将事物放在不同路径,可能用不同的方式编译。

解决方案

解决这些问题的方法是使用一个包存储库中的 .NET。 选择哪个存储库,以及如何选择,皆因用例和 Linux 发行版而异。

我的 Linux 发行版提供 .NET 包,我想使用它们

  • 是否将 Microsoft 存储库用于其他包,例如 PowerShell 和 MSSQL?

    • 将包管理器配置为忽略 Microsoft 存储库中的 .NET 包。 你可能已从两个存储库中安装了 .NET,因此需要选择其中一个存储库。

      1. 从分发版中删除现有 .NET 包。 你想要从头开始,并确保不要从错误的存储库安装它们。

        sudo dnf remove 'dotnet*' 'aspnet*' 'netstandard*'
        
      2. 配置 Microsoft 存储库以忽略任何 .NET 包。

        echo 'excludepkgs=dotnet*,aspnet*,netstandard*' | sudo tee -a /etc/yum.repos.d/microsoft-prod.repo
        
      3. 从分发版的包源重新安装 .NET。 有关详细信息,请参阅在 Linux 上安装 .NET

      1. 从分发版中删除现有 .NET 包。 你想要从头开始,并确保不要从错误的存储库安装它们。

        sudo dnf remove 'dotnet*' 'aspnet*' 'netstandard*'
        
      2. 从分发版中删除 Microsoft 存储库源。

        sudo dnf remove packages-microsoft-prod
        
      3. 从分发版的包源重新安装 .NET。 有关详细信息,请参阅在 Linux 上安装 .NET

  • 是否将 Microsoft 存储库用于其他包,例如 PowerShell 和 MSSQL?

    • 将包管理器配置为忽略 Microsoft 存储库中的 .NET 包。 你可能已从两个存储库中安装了 .NET,因此需要选择其中一个存储库。

      1. 从分发版中删除现有 .NET 包。 你想要从头开始,并确保不要从错误的存储库安装它们。

        sudo apt remove 'dotnet*' 'aspnet*' 'netstandard*'
        
      2. 如果尚不存在,则创建 /etc/apt/preferences

        touch /etc/apt/preferences
        
      3. 在编辑器中打开 /etc/apt/preferences 并添加以下设置,以防止以 dotnetaspnetcorenetstandard 开头的包源自 Microsoft 存储库:

        Package: dotnet* aspnet* netstandard*
        Pin: origin "packages.microsoft.com"
        Pin-Priority: -10
        
      4. 从分发版的包源重新安装 .NET。 有关详细信息,请参阅在 Linux 上安装 .NET

      1. 从分发版中删除现有 .NET 包。 你想要从头开始,并确保不要从错误的存储库安装它们。

        sudo apt remove 'dotnet*' 'aspnet*' 'netstandard*'
        
      2. 从分发版中删除 Microsoft 存储库源。

        sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
        sudo apt update
        
      3. 从分发版的包源重新安装 .NET。 有关详细信息,请参阅在 Linux 上安装 .NET

我需要不是我的 Linux 分发版提供的 .NET 版本

将包管理器配置为忽略分发存储库中的 .NET 包。 你可能已从两个存储库中安装了 .NET,因此需要选择其中一个存储库。

  1. 从分发版中删除现有 .NET 包。 你想要从头开始,并确保不要从错误的存储库安装它们。

    sudo dnf remove 'dotnet*' 'aspnet*' 'netstandard*'
    
  2. 将 Linux 存储库配置为忽略 .NET 包。

    echo 'excludepkgs=dotnet*,aspnet*,netstandard*' | sudo tee -a /etc/yum.repos.d/<your-package-source>.repo
    

    请确保将 <your-package-source> 替换为分发版的包源。

  3. 从分发版的包源重新安装 .NET。 有关详细信息,请参阅在 Linux 上安装 .NET

将包管理器配置为忽略分发存储库中的 .NET 包。 你可能已从两个存储库中安装了 .NET,因此需要选择其中一个存储库。

  1. 从分发版中删除现有 .NET 包。 你想要从头开始,并确保不要从错误的存储库安装它们。

    sudo apt remove 'dotnet*' 'aspnet*' 'netstandard*'
    
  2. 如果尚不存在,则创建 /etc/apt/preferences

    touch /etc/apt/preferences
    
  3. 在编辑器中打开 /etc/apt/preferences 并添加 apt 首选项片段,以防止以 dotnetaspnetcorenetstandard 开头的包源自分发的存储库。

    Package: dotnet* aspnet* netstandard*
    Pin: origin "<your-package-source>"
    Pin-Priority: -10    
    

    请确保将 <your-package-source> 替换为分发版的包源。

    分发可能有多个包源。

    例如,在美国的 Ubuntu 上,可能需要对 archive.ubuntu.com 使用一个片段,对 security.ubuntu.com 使用另一个片段。 用如下所示的空行分隔每个片段:

    Package: dotnet* aspnet* netstandard*
    Pin: origin "archive.ubuntu.com"
    Pin-Priority: -10
    
    Package: dotnet* aspnet* netstandard*
    Pin: origin "security.ubuntu.com"
    Pin-Priority: -10
    

    提示

    使用 apt-cache policy 命令查找源:

    apt-cache policy '?name(dotnet.*)' | grep -v microsoft | grep '/ubuntu' | cut -d"/" -f3 | sort -u
    

    提示

    如果你注册了 Ubuntu .NET 向后移植包存储库,则应取消注册 Ubuntu .NET 向后移植包存储库,而不是将包管理器配置为忽略包含的 .NET 包。 否则,包管理器将从此存储库拉取包索引,然后忽略它,因为此存储库仅包含 .NET 包。 每次调用 apt update 时,这都可有效地降低更新本地包索引的速度。

    使用 apt-cache policy 命令检查是否已注册 Ubuntu .NET 向后移植包存储库:

    apt-cache policy '?name(dotnet.*)' | grep 'ppa.launchpadcontent.net/dotnet/backports' | sort -u
    
  4. 从 Microsoft 包源重新安装 .NET。 有关详细信息,请参阅在 Linux 上安装 .NET。 如果使用 Ubuntu,请参阅我的 Ubuntu 分发版不包含所需的 .NET 版本,或者我需要一个不支持的 .NET 版本

在线参考资料

许多其他用户已报告这些问题。 下面列出了这些问题。 你可以认真通读,了解可能会发生的情况:

另请参阅