.NET Core 跨平臺資源監控庫及 dotnet tool 小工具

痴者工良發表於2020-11-08

簡介

CZGL.SystemInfo 是一個支援 Windows 和 Linux 等平臺的能夠獲取機器硬體資訊、採集機器資源資訊、監控程式資源的庫。

在不引入額外依賴的情況下,使用 .NET Runtime 本身的 API,或通過計算獲得資訊,提供高效能的計算方式以及快取,提高效能,還提供 dotnet tool 工具,通過命令列在終端使用。

由於此庫完全是重寫,因此跟舊版本的 API 完全不同,舊版本地址:

舊版本 GitHub: https://github.com/whuanle/CZGL.SystemInfo/tree/0.1

舊版本使用教程: https://www.cnblogs.com/whuanle/p/12435413.html

Nuget 搜尋 CZGL.SystemInfo 即可安裝,版本為 1.0 。

類庫中每一個屬性和方法,我都加上了貼心的註釋以及 return 示例。

CZGL.SystemInfo.Linux 優化部分程式碼,其餘無變化。

Windows 可以使用 System.Diagnostics.PerformanceCounter 、System.Management.ManagementObjectSearcher 分別獲得效能計算器以及機器的 CPU型號、磁碟序列化號等資訊。

平臺差異而且很難統一,所以如獲取某些硬體的型號序列化,獲得程式資訊的資源資訊,這些需求呼叫系統相關的API或者使用命令列操作,需要自己定製。

dotnet tool 體驗

目前做了個簡單的 dotnet 工具,無需 SDK,runtime 下即可使用。

安裝命令:

dotnet tool install --global csys
# or
dotnet tool install --global csys --version 1.0.3
You can invoke the tool using the following command: csys
Tool 'csys' (version '1.0.2') was successfully installed.

如果在 Linux 下,安裝,還需要設定環境變數:

export PATH="$PATH:/home/{你的使用者名稱}/.dotnet/tools"

安裝完畢後,輸入命令進入小工具:

csys
請輸入命令
+-------命令參考------------------------------+
| 1. 輸入 netinfo 檢視網路詳情                  |
| 2. 輸入 nett 監控網路流量                     |
| 3. 輸入 test ,檢查當前作業系統不相容哪些 API    |
| 4. 輸入 ps 檢視程式資訊                       |
+---------------------------------------------+

注:需要使用超級管理員啟動程式,才能使用 ps 功能;

動圖:

csys

小工具功能不多,有興趣可以下載 Nuget 包,裡面有更多功能。

CZGL.SystemInfo

CZGL.SystemInfo 目前有四個類:DiskInfo、NetworkInfo、ProcessInfo、SystemPlatformInfo,下面一一介紹。

為了避免資源浪費,DiskInfo、NetworkInfo、ProcessInfo 部分屬性使用懶載入,不使用此 API 的情況下,不需要消耗效能。

Install-Package CZGL.SystemInfo -Version 1.0.1

SystemPlatformInfo

靜態類,能夠獲取執行環境資訊和有限的硬體資訊,所有資訊在程式啟動前就已經確定。

其 API 說明及獲得的資料示例如下:

屬性 說明 Windows 示例 Linux 示例
FrameworkDescription 框架平臺(.NET Core、Mono等)資訊 .NET Core 3.1.9 .NET Core 3.1.9
FrameworkVersion 執行時資訊版本 3.1.9 3.1.9
OSArchitecture 作業系統平臺架構 X64 X64
OSPlatformID 獲取作業系統的型別 Win32NT Unix
OSVersion 作業系統核心版本 Microsoft Windows NT 6.2.9200.0 Unix 4.4.0.19041
OSDescription 作業系統的版本描述 Microsoft Windows 10.0.19041 Linux 4.4.0-19041-Microsoft #488-Microsoft Mon Sep 01 13:43:00 PST 2020
ProcessArchitecture 本程式的架構 X64 X64
ProcessorCount 當前計算機上的處理器數 8 8
MachineName 計算機名稱 dell-PC dell-PC
UserName 當前登入到此係統的使用者名稱稱 dell dell
UserDomainName 使用者網路域名稱 dell-PC dell-PC
IsUserInteractive 是否在互動模式中執行 True True
GetLogicalDrives 系統的磁碟和分割槽列表 D:, E:, F:, G:, H:, J:, X:|/, /dev, /sys, /proc, /dev/pts, /run, /run/lock, /run/shm
SystemDirectory 系統根目錄完全路徑 X:\WINDOWS\system32
MemoryPageSize 作業系統記憶體頁一頁的位元組數 4096 4096

SystemPlatformInfo 的 API 不會有跨平臺不相容問題,可以大膽使用。

效果演示:

系統平臺資訊:

執行框架    :    .NET Core 3.1.0
作業系統    :    Microsoft Windows 10.0.17763
作業系統版本    :    Microsoft Windows NT 6.2.9200.0
平臺架構    :    X64
機器名稱    :    aaaa-PC
當前關聯使用者名稱    :    aaa
使用者網路域名    :    aaa-PC
系統已執行時間(毫秒)    :    3227500
Web程式核心框架版本    :    3.1.0
是否在互動模式中執行    :    True
分割槽磁碟    :    D:\, E:\, F:\, G:\, H:\, X:\
系統目錄    :    X:\windows\system32
當前程式已使用實體記憶體    :    20020
當前程式已佔耗CPU時間    :    328.125
系統所有程式各種使用的記憶體    :    System.Collections.Generic.KeyValuePair`2[System.String,System.Int64][]
系統已使用記憶體    :    5988340
VisualStudioVersion    :    16.0

ProcessInfo

需要使用超級管理員啟動程式,才能使用此功能;

記錄某一時刻作業系統的資源資料。此 API 使用時有些地方需要注意,比較監控和重新整理資訊會消耗一些效能資源。

通過兩個靜態方法,可以獲取系統的程式列表:

Dictionary<int,string> value = ProcessInfo.GetProcessList();
ProcessInfo[] value = ProcessInfo.GetProcesses();

或者通過指定的程式 ID 獲取:

ProcessInfo value = ProcessInfo.GetProcess(666);

獲得 ProcessInfo 物件後,必須使用 Refresh() 方法重新整理、擷取當前程式狀態的資訊,才能獲得資訊。

如:

ProcessInfo thisProcess = ProcessInfo.GetCurrentProcess();	// 獲取當前程式的 ProcessInfo 物件
thisProcess.Refresh();

只有當你使用 .Refresh() 時,才會開始初始化,並生成相應的資訊。

獲得的資訊不是動態的,而且儲存某一個節點時刻的程式狀態資料,所以如果需要動態更新,則需要再次執行 .Refresh() 方法。

ProcessInfo 能夠獲得程式使用了多少記憶體以及 CPU 時間,但是無法獲得此程式的實體記憶體使用率以及CPU使用率。如果想獲得使用比率,需要呼叫作業系統 API,或者使用作業系統的其它庫,如 Windows 的 WMI。

如果你想獲得一個程式的 CPU 消耗的比例,可以使用靜態方法:

decimal value = ProcessInfo.GetCpuPercentage(666);

大約 2 秒會重新整理一次,所以請勿一直等待此 API 返回資料,適合單獨計算,不適合跟其它資料綜合。此 API 監控的 CPU 佔比不是很準確。

CPU 是真的難求,你可以檢視論文:

https://www.semanticscholar.org/paper/Late-Breaking%3A-Measuring-Processor-Utilization-in-Friedman/d7e312e32cd6bb6cac4531389c5cc7c80481b9b5?p2df

不斷重新整理 CPU 資料:

            while (true)
            {
                var tmp = Convert.ToInt32(Console.ReadLine());
                var process = ProcessInfo.GetProcess(tmp);
                process.Refresh();                          // 重新整理程式資料
                var cpu = ProcessInfo.GetCpuPercentage(process.ProcessId);
                Console.WriteLine($"程式 {process.ProcessName} CPU : {cpu * 100}%");
            }

記憶體監控

PhysicalUsedMemory 屬性值返回的值表示程式使用的可分頁系統記憶體的當前大小(以位元組為單位)。 系統記憶體是作業系統使用的實體記憶體,分為分頁和非分頁的池。 當不可分頁記憶體未使用時,可以將其傳輸到磁碟上的虛擬記憶體分頁檔案中。

屬性名稱 說明 示例
PhysicalUsedMemory 已用的實體記憶體位元組數 17498112

NetworkInfo

NetworkInfo 能夠獲取網路介面資訊。

NetworkInfo.GetNetworkInfo() 可以獲取當前你的電腦正在連線網際網路的首選網路裝置。

如使用 wifi,獲取到的就是無線網路卡;使用網線上網,獲取到的是乙太網卡。

API 使用示例:

            var info = NetworkInfo.GetNetworkInfo();
            Console.WriteLine("\r\n+++++++++++");
            Console.WriteLine($"    網路卡名稱    {info.Name}");
            Console.WriteLine($"    網路連結速度 {info.Speed / 1000 / 1000} Mbps");
            Console.WriteLine($"    Ipv6       {info.AddressIpv6.ToString()}");
            Console.WriteLine($"    Ipv4       {info.AddressIpv4.ToString()}");
            Console.WriteLine($"    DNS        {string.Join(',', info.DNSAddresses.Select(x => x.ToString()).ToArray())}");
            Console.WriteLine($"    上行流量統計 {info.SendLength / 1024 / 1024} MB");
            Console.WriteLine($"    下行流量統計 {info.ReceivedLength / 1024 / 1024} MB");
            Console.WriteLine($"    網路型別     {info.NetworkType}");
            Console.WriteLine($"    網路卡MAC     {info.Mac}");
            Console.WriteLine($"    網路卡資訊     {info.Trademark}");

Status 屬性可以獲取此網路卡的狀態,其列舉說明如下:

Dormant 5 網路介面不處於傳輸資料包的狀態;它正等待外部事件。
Down 2 網路介面無法傳輸資料包。
LowerLayerDown 7 網路介面無法傳輸資料包,因為它執行在一個或多個其他介面之上,而這些“低層”介面中至少有一個已關閉。
NotPresent 6 由於缺少元件(通常為硬體元件),網路介面無法傳輸資料包。
Testing 3 網路介面正在執行測試。
Unknown 4 網路介面的狀態未知。
Up 1 網路介面已執行,可以傳輸資料包。

NetworkType 可以獲得網路卡介面型別,其列舉比較多,詳細請參考:

https://docs.microsoft.com/zh-cn/dotnet/api/system.net.networkinformation.networkinterfacetype?view=netcore-3.1

通常,監控網路,一時檢查網路是否暢通,二是監控流量。

NetworkInfo.IsAvailable 靜態屬性可以檢查當前機器是否能夠連線網際網路。符合條件的網路卡必須是能夠執行可以傳輸資料包,並且不能是本地迴環地址。如果你是內網,則可能不需要此API,可以自己 ping 內網其它機器,確保網路暢通。

實時監控網路速度的使用方法:

            var info = NetworkInfo.GetNetworkInfo();
                while (true)
                {
                    var tmp = info.GetInternetSpeed(1000);
                    Console.WriteLine($"網路上傳速度:{tmp.Send / 1024} kb/s");
                    Console.WriteLine($"網路下載速度:{tmp.Received / 1024} kb/s");
                    Thread.Sleep(500);
                }

(int Received, int Send) GetInternetSpeed(int Milliseconds) 方法可以監控某個的網路傳輸資料量,時間一般時間設定為 1000 ms。

Received 是下載的流量
Send     是上傳的流量

一般來說,電腦只有一個網路卡在連線網際網路進行工作,所以可以使用:

static (int Received, int send) GetNowInternetSpeed(int Milliseconds)

會自動找到電腦正在用來訪問網際網路的網路卡,並記錄流量大小。

還有個 Speed 屬性,可以查詢到網路卡最大支援速率。

如果是-1,則說明無法獲取此網路卡的連結速度;例如 270_000_000 表示是 270MB(一般指 300M 網路卡) 的連結速度。千兆網路卡是 1000_000_000(1000M)。

其它 API 就不介紹了。

直接反射檢視:

NetworkInterface System.Net.NetworkInformation.SystemNetworkInterface
Id {43538D18-BB0E-4CE2-8F66-613FAC9467BD}
Mac E09D3116D014
Name WLAN
Trademark Intel(R) Centrino(R) Advanced-N 6205
PhysicalMac E09D3116D014
Status Up
NetworkType Wireless80211
Statistics System.Net.NetworkInformation.SystemIPInterfaceStatistics
Ipv4Statistics System.Net.NetworkInformation.SystemIPv4InterfaceStatistics
ReceivedLength 103449771
ReceivedLengthIpv4 103449771
SendLength 23753785
SendLengthIpv4 23753785
IsAvailable True
Speed 300000000
IsSupportIpv4 True
IsSupportIpv6 True
DnsSuffix
DNSAddresses System.Net.NetworkInformation.InternalIPAddressCollection
UnicastIPAddressInformationCollection System.Net.NetworkInformation.UnicastIPAddressInformationCollection
AddressIpv6 fe90::adbb:6aa1:2b1f:ae9b%11
AddressIpv4 192.168.3.3
GetPhysicalMac E69D3116D514

注意,因為有些 API ,Linux 下環境差異比較大,建議使用使用 csys 小工具的 test 命令,檢查有哪些 API 可以在此 Linux 環境中使用。

DiskInfo

DiskInfo 能夠獲取的資訊不多。

可以使用靜態方法獲取所有磁碟的 DiskInfo 物件:

DiskInfo.GetDisks()

直接反射看:

DriveInfo F:\
Id F:\
Name F:\
DriveType Fixed
FileSystem NTFS
FreeSpace 76498378752
TotalSize 112718770176
UsedSize 36220391424

Linux

Nuget 搜尋 CZGL.SystemInfo.Linux 安裝。

在這個庫中,Linux 資源資訊包括 程式計量,記憶體計量,CPU計量,虛擬記憶體計量,各種程式執行資訊計量。

要通過例項化 DynamicInfo 才能獲取。

有 5 個物件用於對映相應資訊。

Tasks:用於統計程式數量,處於不同狀態下的程式數。

CpuState:CPU 使用情況,CPU 各種負載資訊。

Mem:實體記憶體和快取使用情況。

Swap:虛擬記憶體使用情況。

PidInfo:一個程式的執行資源資訊。

他們都有一個 IsSuccess 屬性,用來判斷是否能正常獲取到 Linux 的資訊。

例項化獲取物件

            DynamicInfo info = new DynamicInfo();

直接使用

可以通過方法獲取到相應的物件。

            var item = info.GetTasks();
            Console.WriteLine("系統中共有程式數    :" + item.Total);
            Console.WriteLine("正在執行的程式數    :" + item.Running);
            Console.WriteLine("  程式Id  程式名稱  所屬使用者    優化級  高低優先順序  虛擬記憶體   實體記憶體   共享記憶體 程式狀態  佔用系統CPU(%)   佔用記憶體(%d) ");

輸出

程式統計:

Total    :    93
Running    :    1
Sleeping    :    59
Stopped    :    0
Zombie    :    0


CPU資源統計:

UserSpace    :    1
Sysctl    :    0.6
NI    :    0
Idolt    :    98.3
WaitIO    :    0.1
HardwareIRQ    :    0
SoftwareInterrupts    :    0


記憶體統計:

Total    :    1009048
Used    :    334040
Free    :    85408
Buffers    :    589600
CanUsed    :    675008


獲取虛擬記憶體統計:

Total    :    0
Used    :    0
Free    :    0
AvailMem    :    505744

相關文章