c#在linux上直接用system.io读取/proc和/sys文件即可,无需特殊api;注意空字节、无length、不支持seek、权限与挂载限制、避免streamreader.readline()、禁用缓存、路径需实测。

直接读/proc和/sys文件就行,C#没特殊API
Linux 的 /proc 和 /sys 是虚拟文件系统,内核通过普通文件接口暴露数据。C# 在 Linux 上(.NET 6+)运行时,不需要额外库,System.IO.File.ReadAllText 或 File.ReadAllLines 就能读——只要进程有权限、路径存在、挂载正常。
常见错误是误以为要调用系统调用或依赖 P/Invoke;其实本质就是读文本文件。但要注意:这些“文件”不支持 Seek、不返回真实 Length,部分路径(如 /proc/<pid>/cmdline</pid>)含空字节,不能用 ReadAllText 直接处理。
- 优先用
File.ReadAllBytes+ 手动 UTF-8 解码(跳过 BOM,处理 \0) - 避免对
/proc/sys/kernel/hostname这类路径做File.Exists判断——它可能返回false即使可读,因为某些 procfs 条目不实现stat - 读
/proc/mounts或/proc/cpuinfo这类稳定路径没问题;但读/proc/<pid>/</pid>下内容前,先确认 pid 是否仍存在,否则抛IOException(不是FileNotFoundException)
StreamReader 读 /proc 文件容易卡死或乱码
很多示例直接用 new StreamReader("/proc/cpuinfo"),但实际中会出问题:部分 procfs 文件不按行终止(比如 /proc/sys/net/ipv4/ip_forward 内容就只是单个字符 1 或 0,无换行),StreamReader.ReadLine() 可能阻塞或返回 null;还有些文件(如 /proc/kcore)被设计为不可读取,会触发内核延迟响应。
- 永远指定编码:
new StreamReader(path, Encoding.UTF8),别依赖默认 - 不用
ReadLine()处理单值文件,改用ReadToEnd().Trim('\0', '\n', ' ') - 加超时控制:用
FileStream配合CancellationToken,因为某些路径(如挂载异常的/sys/firmware/acpi/)可能让OpenRead卡住几秒 - 示例:读开关值
var value = File.ReadAllText("/sys/class/power_supply/AC/online").Trim(); // 返回 "1" 或 "0"
权限、挂载点和容器环境导致路径不可达
在 Docker 容器或 systemd-nspawn 环境里,/proc 和 /sys 默认只挂载了子集。比如容器里 /proc/sys 往往不可写,且 /proc/sys/fs/file-max 可能读不到(因 sysctl 命名空间隔离);Kubernetes Pod 若未加 hostPID: true,/proc/1/ 都访问不了。
- 检查挂载:运行
mount | grep -E "(proc|sysfs)"确认是否 full mount - 容器内优先读
/proc/self/下内容(如/proc/self/cgroup),它总是可用 - 不要硬编码
/sys/devices/system/cpu/online—— 某些 ARM 设备该路径不存在,应 fallback 到/sys/devices/system/cpu/present - 权限失败时错误信息是
UnauthorizedAccessException,不是IOException;此时需检查容器是否以--privileged启动,或添加cap_add: [SYS_ADMIN]
别把 /sys 当配置文件去写,也别缓存 /proc 值太久
/sys 下多数文件是只读的(比如 /sys/class/net/eth0/operstate),尝试写入会立刻报 IOException(错误信息类似 "Operation not supported")。而 /proc 数据天生动态:CPU 使用率、内存剩余量、进程数每秒都在变,缓存 5 秒以上基本就失去意义。
- 写
/sys前先查文档确认是否可写;例如/sys/class/leds/*/brightness可写,但/sys/class/thermal/thermal_zone*/mode在多数发行版默认只读 - 避免用
Lazy<string></string>缓存/proc/meminfo结果——它可能在你读第二次时已失效 - 高频采集(如监控 agent)建议用
Span<byte></byte>+ReadOnlySpan<char></char>解析,避免反复分配字符串;/proc/stat每行字段位置固定,可按空格切分后索引取值,比正则快 3–5 倍
最麻烦的其实是路径语义不一致:同一份信息在不同内核版本可能散落在 /proc、/sys、甚至 /sys/firmware/devicetree 里,而且没有统一 schema。得靠实测,不能只信文档。










