ComputerUtil.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. // 大名科技(天津)有限公司版权所有 电话:18020030720 QQ:515096995
  2. //
  3. // 此源代码遵循位于源代码树根目录中的 LICENSE 文件的许可证
  4. namespace Admin.NET.Core;
  5. public static class ComputerUtil
  6. {
  7. /// <summary>
  8. /// 内存信息
  9. /// </summary>
  10. /// <returns></returns>
  11. public static MemoryMetrics GetComputerInfo()
  12. {
  13. MemoryMetricsClient client = new();
  14. MemoryMetrics memoryMetrics;
  15. if (IsMacOS())
  16. {
  17. memoryMetrics = client.GetMacOSMetrics();
  18. }
  19. else if (IsUnix())
  20. {
  21. memoryMetrics = client.GetUnixMetrics();
  22. }
  23. else
  24. {
  25. memoryMetrics = client.GetWindowsMetrics();
  26. }
  27. memoryMetrics.FreeRam = Math.Round(memoryMetrics.Free / 1024, 2) + "GB";
  28. memoryMetrics.UsedRam = Math.Round(memoryMetrics.Used / 1024, 2) + "GB";
  29. memoryMetrics.TotalRam = Math.Round(memoryMetrics.Total / 1024, 2) + "GB";
  30. memoryMetrics.RamRate = Math.Ceiling(100 * memoryMetrics.Used / memoryMetrics.Total).ToString() + "%";
  31. memoryMetrics.CpuRate = Math.Ceiling(GetCPURate().ParseToDouble()) + "%";
  32. return memoryMetrics;
  33. }
  34. /// <summary>
  35. /// 获取正确的操作系统版本(Linux获取发行版本)
  36. /// </summary>
  37. /// <returns></returns>
  38. public static String GetOSInfo()
  39. {
  40. string opeartion = string.Empty;
  41. if (IsMacOS())
  42. {
  43. var output = ShellHelper.Bash("sw_vers | awk 'NR<=2{printf \"%s \", $NF}'");
  44. if (output != null)
  45. {
  46. opeartion = output.Replace("%", string.Empty);
  47. }
  48. }
  49. else if (IsUnix())
  50. {
  51. var output = ShellHelper.Bash("awk -F= '/^VERSION_ID/ {print $2}' /etc/os-release | tr -d '\"'");
  52. opeartion = output ?? string.Empty;
  53. }
  54. else
  55. {
  56. opeartion = RuntimeInformation.OSDescription;
  57. }
  58. return opeartion;
  59. }
  60. /// <summary>
  61. /// 磁盘信息
  62. /// </summary>
  63. /// <returns></returns>
  64. public static List<DiskInfo> GetDiskInfos()
  65. {
  66. var diskInfos = new List<DiskInfo>();
  67. if (IsMacOS())
  68. {
  69. var output = ShellHelper.Bash(@"df -m | awk '/^\/dev\/disk/ {print $1,$2,$3,$4,$5}'");
  70. var disks = output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
  71. if (disks.Length < 1) return diskInfos;
  72. foreach (var item in disks)
  73. {
  74. var disk = item.Split(' ', (char)StringSplitOptions.RemoveEmptyEntries);
  75. if (disk == null || disk.Length < 5)
  76. continue;
  77. var diskInfo = new DiskInfo()
  78. {
  79. DiskName = disk[0],
  80. TypeName = ShellHelper.Bash("diskutil info " + disk[0] + " | awk '/File System Personality/ {print $4}'").Replace("\n", string.Empty),
  81. TotalSize = long.Parse(disk[1]) / 1024,
  82. Used = long.Parse(disk[2]) / 1024,
  83. AvailableFreeSpace = long.Parse(disk[3]) / 1024,
  84. AvailablePercent = decimal.Parse(disk[4].Replace("%", ""))
  85. };
  86. diskInfos.Add(diskInfo);
  87. }
  88. }
  89. else if (IsUnix())
  90. {
  91. var output = ShellHelper.Bash(@"df -mT | awk '/^\/dev\/(sd|vd|xvd|nvme|sda|vda)/ {print $1,$2,$3,$4,$5,$6}'");
  92. var disks = output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
  93. if (disks.Length < 1) return diskInfos;
  94. //var rootDisk = disks[1].Split(' ', (char)StringSplitOptions.RemoveEmptyEntries);
  95. //if (rootDisk == null || rootDisk.Length < 1)
  96. // return diskInfos;
  97. foreach (var item in disks)
  98. {
  99. var disk = item.Split(' ', (char)StringSplitOptions.RemoveEmptyEntries);
  100. if (disk == null || disk.Length < 6)
  101. continue;
  102. var diskInfo = new DiskInfo()
  103. {
  104. DiskName = disk[0],
  105. TypeName = disk[1],
  106. TotalSize = long.Parse(disk[2]) / 1024,
  107. Used = long.Parse(disk[3]) / 1024,
  108. AvailableFreeSpace = long.Parse(disk[4]) / 1024,
  109. AvailablePercent = decimal.Parse(disk[5].Replace("%", ""))
  110. };
  111. diskInfos.Add(diskInfo);
  112. }
  113. }
  114. else
  115. {
  116. var driv = DriveInfo.GetDrives().Where(u => u.IsReady);
  117. foreach (var item in driv)
  118. {
  119. if (item.DriveType == DriveType.CDRom) continue;
  120. var obj = new DiskInfo()
  121. {
  122. DiskName = item.Name,
  123. TypeName = item.DriveType.ToString(),
  124. TotalSize = item.TotalSize / 1024 / 1024 / 1024,
  125. AvailableFreeSpace = item.AvailableFreeSpace / 1024 / 1024 / 1024,
  126. };
  127. obj.Used = obj.TotalSize - obj.AvailableFreeSpace;
  128. obj.AvailablePercent = decimal.Ceiling(obj.Used / (decimal)obj.TotalSize * 100);
  129. diskInfos.Add(obj);
  130. }
  131. }
  132. return diskInfos;
  133. }
  134. /// <summary>
  135. /// 获取外网IP地址
  136. /// </summary>
  137. /// <returns></returns>
  138. public static string GetIpFromOnline()
  139. {
  140. var url = "https://www.ip.cn/api/index?ip&type=0";
  141. var str = url.GetAsStringAsync().GetAwaiter().GetResult();
  142. var resp = JSON.Deserialize<IpCnResp>(str);
  143. return resp.Ip + " " + resp.Address;
  144. }
  145. public static bool IsUnix()
  146. {
  147. return RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
  148. }
  149. public static bool IsMacOS()
  150. {
  151. return RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
  152. }
  153. public static string GetCPURate()
  154. {
  155. string cpuRate;
  156. if (IsMacOS())
  157. {
  158. string output = ShellUtil.Bash("top -l 1 | grep \"CPU usage\" | awk '{print $3 + $5}'");
  159. cpuRate = output.Trim();
  160. }
  161. else if (IsUnix())
  162. {
  163. string output = ShellUtil.Bash("top -b -n1 | grep \"Cpu(s)\" | awk '{print $2 + $4}'");
  164. cpuRate = output.Trim();
  165. }
  166. else
  167. {
  168. string output = ShellUtil.Cmd("wmic", "cpu get LoadPercentage");
  169. cpuRate = output.Replace("LoadPercentage", string.Empty).Trim();
  170. }
  171. return cpuRate;
  172. }
  173. /// <summary>
  174. /// 获取系统运行时间
  175. /// </summary>
  176. /// <returns></returns>
  177. public static string GetRunTime()
  178. {
  179. string runTime = string.Empty;
  180. if (IsMacOS())
  181. {
  182. //macOS 获取系统启动时间:
  183. //sysctl -n kern.boottime | awk '{print $4}' | tr -d ','
  184. //返回:1705379131
  185. //使用date格式化即可
  186. string output = ShellUtil.Bash("date -r $(sysctl -n kern.boottime | awk '{print $4}' | tr -d ',') +\"%Y-%m-%d %H:%M:%S\"").Trim();
  187. runTime = DateTimeUtil.FormatTime((DateTime.Now - output.ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
  188. }
  189. else if (IsUnix())
  190. {
  191. string output = ShellUtil.Bash("uptime -s").Trim();
  192. runTime = DateTimeUtil.FormatTime((DateTime.Now - output.ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
  193. }
  194. else
  195. {
  196. string output = ShellUtil.Cmd("wmic", "OS get LastBootUpTime/Value");
  197. string[] outputArr = output.Split('=', (char)StringSplitOptions.RemoveEmptyEntries);
  198. if (outputArr.Length == 2)
  199. runTime = DateTimeUtil.FormatTime((DateTime.Now - outputArr[1].Split('.')[0].ParseToDateTime()).TotalMilliseconds.ToString().Split('.')[0].ParseToLong());
  200. }
  201. return runTime;
  202. }
  203. }
  204. /// <summary>
  205. /// IP信息
  206. /// </summary>
  207. public class IpCnResp
  208. {
  209. public string Ip { get; set; }
  210. public string Address { get; set; }
  211. }
  212. /// <summary>
  213. /// 内存信息
  214. /// </summary>
  215. public class MemoryMetrics
  216. {
  217. [Newtonsoft.Json.JsonIgnore]
  218. [System.Text.Json.Serialization.JsonIgnore]
  219. public double Total { get; set; }
  220. [Newtonsoft.Json.JsonIgnore]
  221. [System.Text.Json.Serialization.JsonIgnore]
  222. public double Used { get; set; }
  223. [Newtonsoft.Json.JsonIgnore]
  224. [System.Text.Json.Serialization.JsonIgnore]
  225. public double Free { get; set; }
  226. /// <summary>
  227. /// 已用内存
  228. /// </summary>
  229. public string UsedRam { get; set; }
  230. /// <summary>
  231. /// CPU使用率%
  232. /// </summary>
  233. public string CpuRate { get; set; }
  234. /// <summary>
  235. /// 总内存 GB
  236. /// </summary>
  237. public string TotalRam { get; set; }
  238. /// <summary>
  239. /// 内存使用率 %
  240. /// </summary>
  241. public string RamRate { get; set; }
  242. /// <summary>
  243. /// 空闲内存
  244. /// </summary>
  245. public string FreeRam { get; set; }
  246. }
  247. /// <summary>
  248. /// 磁盘信息
  249. /// </summary>
  250. public class DiskInfo
  251. {
  252. /// <summary>
  253. /// 磁盘名
  254. /// </summary>
  255. public string DiskName { get; set; }
  256. /// <summary>
  257. /// 类型名
  258. /// </summary>
  259. public string TypeName { get; set; }
  260. /// <summary>
  261. /// 总剩余
  262. /// </summary>
  263. public long TotalFree { get; set; }
  264. /// <summary>
  265. /// 总量
  266. /// </summary>
  267. public long TotalSize { get; set; }
  268. /// <summary>
  269. /// 已使用
  270. /// </summary>
  271. public long Used { get; set; }
  272. /// <summary>
  273. /// 可使用
  274. /// </summary>
  275. public long AvailableFreeSpace { get; set; }
  276. /// <summary>
  277. /// 使用百分比
  278. /// </summary>
  279. public decimal AvailablePercent { get; set; }
  280. }
  281. public class MemoryMetricsClient
  282. {
  283. /// <summary>
  284. /// windows系统获取内存信息
  285. /// </summary>
  286. /// <returns></returns>
  287. public MemoryMetrics GetWindowsMetrics()
  288. {
  289. string output = ShellUtil.Cmd("wmic", "OS get FreePhysicalMemory,TotalVisibleMemorySize /Value");
  290. var metrics = new MemoryMetrics();
  291. var lines = output.Trim().Split('\n', (char)StringSplitOptions.RemoveEmptyEntries);
  292. if (lines.Length <= 0) return metrics;
  293. var freeMemoryParts = lines[0].Split('=', (char)StringSplitOptions.RemoveEmptyEntries);
  294. var totalMemoryParts = lines[1].Split('=', (char)StringSplitOptions.RemoveEmptyEntries);
  295. metrics.Total = Math.Round(double.Parse(totalMemoryParts[1]) / 1024, 0);
  296. metrics.Free = Math.Round(double.Parse(freeMemoryParts[1]) / 1024, 0);//m
  297. metrics.Used = metrics.Total - metrics.Free;
  298. return metrics;
  299. }
  300. /// <summary>
  301. /// Unix系统获取
  302. /// </summary>
  303. /// <returns></returns>
  304. public MemoryMetrics GetUnixMetrics()
  305. {
  306. string output = ShellUtil.Bash("free -m | awk '{print $2,$3,$4,$5,$6}'");
  307. var metrics = new MemoryMetrics();
  308. var lines = output.Split('\n', (char)StringSplitOptions.RemoveEmptyEntries);
  309. if (lines.Length <= 0) return metrics;
  310. if (lines != null && lines.Length > 0)
  311. {
  312. var memory = lines[1].Split(' ', (char)StringSplitOptions.RemoveEmptyEntries);
  313. if (memory.Length >= 3)
  314. {
  315. metrics.Total = double.Parse(memory[0]);
  316. metrics.Used = double.Parse(memory[1]);
  317. metrics.Free = double.Parse(memory[2]);//m
  318. }
  319. }
  320. return metrics;
  321. }
  322. /// <summary>
  323. /// macOS系统获取
  324. /// </summary>
  325. /// <returns></returns>
  326. public MemoryMetrics GetMacOSMetrics()
  327. {
  328. var metrics = new MemoryMetrics();
  329. //物理内存大小
  330. var total = ShellUtil.Bash("sysctl -n hw.memsize | awk '{printf \"%.2f\", $1/1024/1024}'");
  331. metrics.Total = float.Parse(total.Replace("%", string.Empty));
  332. //TODO:占用内存,检查效率
  333. var free = ShellUtil.Bash("top -l 1 -s 0 | awk '/PhysMem/ {print $6+$8}'");
  334. metrics.Free = float.Parse(free);
  335. metrics.Used = metrics.Total - metrics.Free;
  336. return metrics;
  337. }
  338. }
  339. public class ShellUtil
  340. {
  341. /// <summary>
  342. /// linux 系统命令
  343. /// </summary>
  344. /// <param name="command"></param>
  345. /// <returns></returns>
  346. public static string Bash(string command)
  347. {
  348. var escapedArgs = command.Replace("\"", "\\\"");
  349. var process = new Process()
  350. {
  351. StartInfo = new ProcessStartInfo
  352. {
  353. FileName = "/bin/bash",
  354. Arguments = $"-c \"{escapedArgs}\"",
  355. RedirectStandardOutput = true,
  356. UseShellExecute = false,
  357. CreateNoWindow = true,
  358. }
  359. };
  360. process.Start();
  361. string result = process.StandardOutput.ReadToEnd();
  362. process.WaitForExit();
  363. process.Dispose();
  364. return result;
  365. }
  366. /// <summary>
  367. /// windows系统命令
  368. /// </summary>
  369. /// <param name="fileName"></param>
  370. /// <param name="args"></param>
  371. /// <returns></returns>
  372. public static string Cmd(string fileName, string args)
  373. {
  374. string output = string.Empty;
  375. var info = new ProcessStartInfo();
  376. info.FileName = fileName;
  377. info.Arguments = args;
  378. info.RedirectStandardOutput = true;
  379. using (var process = Process.Start(info))
  380. {
  381. output = process.StandardOutput.ReadToEnd();
  382. }
  383. return output;
  384. }
  385. }
  386. public class ShellHelper
  387. {
  388. /// <summary>
  389. /// Linux 系统命令
  390. /// </summary>
  391. /// <param name="command"></param>
  392. /// <returns></returns>
  393. public static string Bash(string command)
  394. {
  395. var escapedArgs = command.Replace("\"", "\\\"");
  396. var process = new Process()
  397. {
  398. StartInfo = new ProcessStartInfo
  399. {
  400. FileName = "/bin/bash",
  401. Arguments = $"-c \"{escapedArgs}\"",
  402. RedirectStandardOutput = true,
  403. UseShellExecute = false,
  404. CreateNoWindow = true,
  405. }
  406. };
  407. process.Start();
  408. string result = process.StandardOutput.ReadToEnd();
  409. process.WaitForExit();
  410. process.Dispose();
  411. return result;
  412. }
  413. /// <summary>
  414. /// Windows 系统命令
  415. /// </summary>
  416. /// <param name="fileName"></param>
  417. /// <param name="args"></param>
  418. /// <returns></returns>
  419. public static string Cmd(string fileName, string args)
  420. {
  421. string output = string.Empty;
  422. var info = new ProcessStartInfo();
  423. info.FileName = fileName;
  424. info.Arguments = args;
  425. info.RedirectStandardOutput = true;
  426. using (var process = Process.Start(info))
  427. {
  428. output = process.StandardOutput.ReadToEnd();
  429. }
  430. return output;
  431. }
  432. }