ComputerUtil.cs 15 KB

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