Files
MoShiro/backend/shared/MoShiro.Measurement/Platform/PlatformDetector.cs
T
justme 2e146d4da7
ci/woodpecker/push/main-amd64-build Pipeline was successful
refactor!: rename the project from Monitor to MoShiro [CI]
Namespaces, assemblies, solution, binaries, images, systemd units, config paths, environment variables, protocol methods and the Linux user are all renamed. Breaking: existing databases, node identities and installed units must be recreated.
2026-10-07 02:03:25 +08:00

82 lines
3.1 KiB
C#

using System.Runtime.InteropServices;
using MoShiro.Protocol;
namespace MoShiro.Measurement;
/// <summary>
/// 读出本机的系统名和架构,只用于在面板上展示。故意只取粗粒度的信息:
/// 「Debian 12」「Windows 11」「x64」,不读主机名、内核版本、CPU 型号。
/// </summary>
public static class PlatformDetector
{
public static PlatformInfo Detect()
{
PlatformInfo info = Detect(File.Exists("/etc/os-release") ? File.ReadAllLines("/etc/os-release") : []);
info.Version = Empty(BuildInfo.Version);
info.Tag = Empty(BuildInfo.Tag);
info.Commit = Empty(BuildInfo.Commit);
info.BuiltAt = Empty(BuildInfo.BuiltAt);
return info;
}
private static string? Empty(string value) => value.Length == 0 ? null : value;
/// <summary>`osRelease` 是 /etc/os-release 的各行(Linux 之外不用)。拆出来是为了好测。</summary>
internal static PlatformInfo Detect(IEnumerable<string> osRelease)
{
string arch = RuntimeInformation.OSArchitecture switch
{
Architecture.X64 => "x64",
Architecture.Arm64 => "arm64",
Architecture.Arm => "arm",
Architecture.X86 => "x86",
var other => other.ToString().ToLowerInvariant(),
};
if (OperatingSystem.IsWindows())
{
// Windows 11 的版本号还是 10.0,靠内部版本号(22000 起)区分
string name = Environment.OSVersion.Version.Build >= 22000 ? "Windows 11" : "Windows 10";
return new PlatformInfo { Os = "windows", Name = name, Arch = arch };
}
if (OperatingSystem.IsMacOS())
{
return new PlatformInfo { Os = "macos", Name = "macOS", Arch = arch };
}
if (OperatingSystem.IsLinux())
{
return new PlatformInfo { Os = "linux", Name = LinuxName(osRelease), Arch = arch };
}
return new PlatformInfo { Os = "other", Name = null, Arch = arch };
}
/// <summary>从 os-release 里取发行版名字和主版本:「Debian GNU/Linux 12 (bookworm)」→「Debian 12」,「OpenWrt 24.10.0」→「OpenWrt 24.10」。</summary>
internal static string LinuxName(IEnumerable<string> osRelease)
{
var values = new Dictionary<string, string>(StringComparer.Ordinal);
foreach (string line in osRelease)
{
int eq = line.IndexOf('=', StringComparison.Ordinal);
if (eq > 0)
{
values[line[..eq].Trim()] = line[(eq + 1)..].Trim().Trim('"', '\'');
}
}
string name = values.GetValueOrDefault("NAME") ?? values.GetValueOrDefault("ID") ?? "Linux";
name = name.Replace(" GNU/Linux", string.Empty, StringComparison.Ordinal).Trim();
string? version = values.GetValueOrDefault("VERSION_ID");
if (string.IsNullOrEmpty(version))
{
return name;
}
// 只留 主.次:Alpine 的 3.22.1、OpenWrt 的 24.10.0 都截成两段;Debian 的 12 本来就一段
string[] parts = version.Split('.');
return $"{name} {string.Join('.', parts.Take(2))}";
}
}