ComputerUtil.cs 15 KB

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