一、时区问题
1.1 问题现象
1.2 根本原因
差异点 | Windows | Linux |
时区数据库 | Windows 注册表时区 ID | IANA 时区数据库(tzdata) |
中国时区 ID | China Standard Time
| Asia/Shanghai
|
默认时区 | 跟随系统区域设置 | 多数服务器/Docker 镜像默认为 UTC |
夏令时 | 部分时区支持 | 由 tzdata 统一管理 |
.NET Core/.NET 5+ 在 Linux 上使用 IANA 时区标准,与 Windows 时区 ID 不兼容。
1.3 解决方案
方案一:系统级设置时区(推荐)
方案二:环境变量 TZ(Docker 常用)
方案三:挂载宿主机时区文件
方案四:代码内跨平台时区转换
1.4 最佳实践
存储用 UTC,显示转本地:数据库统一存 UTC,展示时按用户时区转换
优先使用 DateTimeOffset:自带偏移量信息,跨平台更安全
Docker 镜像显式设置 TZ:不要依赖宿主机默认值
定时任务用 UTC 或明确时区:避免夏令时切换导致执行异常
二、编码问题
2.1 问题现象
2.2 根本原因
.NET Core/.NET 5+ 默认仅内置 UTF-8、UTF-16、ASCII 等少数编码。GBK/GB2312(代码页 936)等 Windows 常用代码页需要通过 System.Text.Encoding.CodePages NuGet 包显式注册才能使用。
Linux 系统默认 locale 多为 en_US.UTF-8,控制台不支持中文输出时也会显示异常。
2.3 解决方案
步骤 1:安装 NuGet 包
步骤 2:程序入口处注册代码页提供程序
注意:整个 AppDomain 只需注册一次,重复注册无害。ASP.NET Core 推荐放在 Program.cs 最开头或 Startup.ConfigureServices 顶部。
步骤 3:正确读取指定编码文件
步骤 4:控制台输出中文设置
步骤 5:Linux 系统 locale 设置
2.4 常见编码对照表
2.5 最佳实践
新项目统一使用 UTF-8:源码、配置文件、日志全部 UTF-8
读取外部文件显式指定编码:不要依赖系统默认编码
用代码页编号替代名称:Encoding.GetEncoding(936) 比 "GBK" 更可靠
注册代码页放在程序最开头:避免任何编码操作在注册前执行
编码转换正确姿势:先用源编码解码为 string,再用目标编码编码
三、权限问题
3.1 问题现象
3.2 常见权限错误与修复
3.2.1 文件/目录权限不足
修复方案:
3.2.2 低端口绑定权限
Linux 中 1024 以下端口需要 root 权限才能绑定。
方案一:使用高位端口(推荐)
方案二:赋予程序端口绑定能力
3.2.3 以专用用户运行应用
生产环境不应以 root 运行 .NET 应用。
3.2.4 SELinux 权限问题
CentOS/RHEL 默认启用 SELinux,可能阻止 .NET 应用的文件访问、网络绑定等。
3.3 systemd 服务部署权限配置
3.4 Docker 容器权限最佳实践
3.5 权限排查命令速查
四、综合工具类源码
4.1 LinuxDeploymentHelper.cs
4.2 使用示例
五、部署检查清单
部署完成后,按以下清单逐项验证:
六、总结
三大问题的核心解决思路:
时区:系统层面设置 Asia/Shanghai,代码层面区分 Windows/Linux 时区 ID,存储优先 UTC
编码:注册 CodePagesEncodingProvider,读写文件显式指定编码,新项目统一 UTF-8
权限:专用用户运行,遵循最小权限原则,注意低端口和 SELinux 限制
掌握以上要点,可以解决 90% 以上的 .NET 跨 Linux 部署基础问题。
关注评论或者回复【777】得:《.NET 程序部署 Linux,时区、编码、权限常见问题汇总的详细实战资料和完整源码》