.NET 6 Linux独立控制台应用环境名称为空,无法加载配置
问题
在Linux上的.NET 6控制台应用中,尝试从appsettings.{environment}.json加载配置,使用的代码如下:
private static async Task Main(string[] args) { using IHost host = Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, configuration) => { // IHostEnvironment env = hostingContext.HostingEnvironment; // ==> env.EnvironmentName 为空 string? environmentName = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT"); if (string.IsNullOrWhiteSpace(environmentName)) environmentName = string.Empty; configuration.AddJsonFile("./appsettings.json"); // ==> 此处environmentName也为空! configuration.AddJsonFile($"./appsettings.{environmentName}.json".ToLowerInvariant()); }) ... }
已在~/.bashrc中添加export DOTNET_ENVIRONMENT=somename配置环境变量,通过echo $DOTNET_ENVIRONMENT可正常查看该变量值,但通过SSH连接Linux机器并执行./MyApp(自包含应用)时,运行时获取的环境名称为空值,请问可能是什么原因?
可能的原因及解决办法
环境变量未在当前会话中生效
修改~/.bashrc后,需要重新加载配置才能让变量生效。如果修改后没有重启SSH会话或执行source ~/.bashrc,当前会话的环境变量不会更新。可以先执行source ~/.bashrc,再运行应用测试。
另外,部分SSH连接可能以非交互式shell启动,此时~/.bashrc不会被自动加载。可以检查shell模式,或者将环境变量配置到~/.profile或~/.bash_profile中(这类文件在登录shell时会加载)。使用sudo运行应用导致环境变量丢失
如果执行应用时使用了sudo ./MyApp,sudo会重置大部分环境变量,包括DOTNET_ENVIRONMENT。此时可以通过sudo -E ./MyApp保留当前用户的环境变量,或者直接以当前用户权限运行应用。自定义配置逻辑覆盖了默认行为
Host.CreateDefaultBuilder(args)已经默认实现了以下配置逻辑:- 读取
DOTNET_ENVIRONMENT环境变量设置运行环境 - 自动加载
appsettings.json和appsettings.{EnvironmentName}.json
你手动添加的配置代码可能因为执行顺序问题,导致环境变量读取时机不对。可以尝试移除自定义的ConfigureAppConfiguration逻辑,直接使用默认配置,或者调整逻辑顺序:
using IHost host = Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, configuration) => { // 先让默认逻辑加载环境变量 var env = hostingContext.HostingEnvironment; // 此时env.EnvironmentName应该已正确获取 configuration.AddJsonFile("./appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"./appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); }) ...- 读取
自包含应用发布时的配置问题
如果发布自包含应用时指定了环境变量参数,可能会覆盖运行时的环境变量设置。可以检查发布命令是否包含类似/p:EnvironmentName=Production的参数,这类参数会将环境信息嵌入应用,导致运行时读取不到外部设置的DOTNET_ENVIRONMENT。
内容的提问来源于stack exchange,提问作者AlexB

