node-os-utils 1.3.7 → 2.0.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/README.md +1113 -237
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/package.json +99 -0
  4. package/dist/src/adapters/adapter-factory.d.ts +87 -0
  5. package/dist/src/adapters/adapter-factory.d.ts.map +1 -0
  6. package/dist/src/adapters/adapter-factory.js +272 -0
  7. package/dist/src/adapters/adapter-factory.js.map +1 -0
  8. package/dist/src/adapters/linux-adapter.d.ts +199 -0
  9. package/dist/src/adapters/linux-adapter.d.ts.map +1 -0
  10. package/dist/src/adapters/linux-adapter.js +1308 -0
  11. package/dist/src/adapters/linux-adapter.js.map +1 -0
  12. package/dist/src/adapters/macos-adapter.d.ts +232 -0
  13. package/dist/src/adapters/macos-adapter.d.ts.map +1 -0
  14. package/dist/src/adapters/macos-adapter.js +1144 -0
  15. package/dist/src/adapters/macos-adapter.js.map +1 -0
  16. package/dist/src/adapters/windows-adapter.d.ts +124 -0
  17. package/dist/src/adapters/windows-adapter.d.ts.map +1 -0
  18. package/dist/src/adapters/windows-adapter.js +601 -0
  19. package/dist/src/adapters/windows-adapter.js.map +1 -0
  20. package/dist/src/core/base-monitor.d.ts +107 -0
  21. package/dist/src/core/base-monitor.d.ts.map +1 -0
  22. package/dist/src/core/base-monitor.js +312 -0
  23. package/dist/src/core/base-monitor.js.map +1 -0
  24. package/dist/src/core/cache-manager.d.ts +157 -0
  25. package/dist/src/core/cache-manager.d.ts.map +1 -0
  26. package/dist/src/core/cache-manager.js +315 -0
  27. package/dist/src/core/cache-manager.js.map +1 -0
  28. package/dist/src/core/platform-adapter.d.ts +197 -0
  29. package/dist/src/core/platform-adapter.d.ts.map +1 -0
  30. package/dist/src/core/platform-adapter.js +244 -0
  31. package/dist/src/core/platform-adapter.js.map +1 -0
  32. package/dist/src/index.d.ts +205 -0
  33. package/dist/src/index.d.ts.map +1 -0
  34. package/dist/src/index.js +315 -0
  35. package/dist/src/index.js.map +1 -0
  36. package/dist/src/monitors/cpu-monitor.d.ts +139 -0
  37. package/dist/src/monitors/cpu-monitor.d.ts.map +1 -0
  38. package/dist/src/monitors/cpu-monitor.js +433 -0
  39. package/dist/src/monitors/cpu-monitor.js.map +1 -0
  40. package/dist/src/monitors/disk-monitor.d.ts +136 -0
  41. package/dist/src/monitors/disk-monitor.d.ts.map +1 -0
  42. package/dist/src/monitors/disk-monitor.js +465 -0
  43. package/dist/src/monitors/disk-monitor.js.map +1 -0
  44. package/dist/src/monitors/memory-monitor.d.ts +136 -0
  45. package/dist/src/monitors/memory-monitor.d.ts.map +1 -0
  46. package/dist/src/monitors/memory-monitor.js +443 -0
  47. package/dist/src/monitors/memory-monitor.js.map +1 -0
  48. package/dist/src/monitors/network-monitor.d.ts +166 -0
  49. package/dist/src/monitors/network-monitor.d.ts.map +1 -0
  50. package/dist/src/monitors/network-monitor.js +586 -0
  51. package/dist/src/monitors/network-monitor.js.map +1 -0
  52. package/dist/src/monitors/process-monitor.d.ts +142 -0
  53. package/dist/src/monitors/process-monitor.d.ts.map +1 -0
  54. package/dist/src/monitors/process-monitor.js +460 -0
  55. package/dist/src/monitors/process-monitor.js.map +1 -0
  56. package/dist/src/monitors/system-monitor.d.ts +173 -0
  57. package/dist/src/monitors/system-monitor.d.ts.map +1 -0
  58. package/dist/src/monitors/system-monitor.js +592 -0
  59. package/dist/src/monitors/system-monitor.js.map +1 -0
  60. package/dist/src/types/common.d.ts +135 -0
  61. package/dist/src/types/common.d.ts.map +1 -0
  62. package/dist/src/types/common.js +141 -0
  63. package/dist/src/types/common.js.map +1 -0
  64. package/dist/src/types/config.d.ts +288 -0
  65. package/dist/src/types/config.d.ts.map +1 -0
  66. package/dist/src/types/config.js +3 -0
  67. package/dist/src/types/config.js.map +1 -0
  68. package/dist/src/types/errors.d.ts +40 -0
  69. package/dist/src/types/errors.d.ts.map +1 -0
  70. package/dist/src/types/errors.js +67 -0
  71. package/dist/src/types/errors.js.map +1 -0
  72. package/dist/src/types/index.d.ts +16 -0
  73. package/dist/src/types/index.d.ts.map +1 -0
  74. package/dist/src/types/index.js +36 -0
  75. package/dist/src/types/index.js.map +1 -0
  76. package/dist/src/types/monitors.d.ts +623 -0
  77. package/dist/src/types/monitors.d.ts.map +1 -0
  78. package/dist/src/types/monitors.js +3 -0
  79. package/dist/src/types/monitors.js.map +1 -0
  80. package/dist/src/types/platform.d.ts +435 -0
  81. package/dist/src/types/platform.d.ts.map +1 -0
  82. package/dist/src/types/platform.js +3 -0
  83. package/dist/src/types/platform.js.map +1 -0
  84. package/dist/src/utils/command-executor.d.ts +58 -0
  85. package/dist/src/utils/command-executor.d.ts.map +1 -0
  86. package/dist/src/utils/command-executor.js +321 -0
  87. package/dist/src/utils/command-executor.js.map +1 -0
  88. package/dist/test/config/test-config.d.ts +301 -0
  89. package/dist/test/config/test-config.d.ts.map +1 -0
  90. package/dist/test/config/test-config.js +235 -0
  91. package/dist/test/config/test-config.js.map +1 -0
  92. package/dist/test/platform/linux.test.d.ts +6 -0
  93. package/dist/test/platform/linux.test.d.ts.map +1 -0
  94. package/dist/test/platform/linux.test.js +307 -0
  95. package/dist/test/platform/linux.test.js.map +1 -0
  96. package/dist/test/platform/macos.test.d.ts +6 -0
  97. package/dist/test/platform/macos.test.d.ts.map +1 -0
  98. package/dist/test/platform/macos.test.js +276 -0
  99. package/dist/test/platform/macos.test.js.map +1 -0
  100. package/dist/test/platform/windows.test.d.ts +6 -0
  101. package/dist/test/platform/windows.test.d.ts.map +1 -0
  102. package/dist/test/platform/windows.test.js +320 -0
  103. package/dist/test/platform/windows.test.js.map +1 -0
  104. package/dist/test/unit/adapters/adapter-factory.test.d.ts +2 -0
  105. package/dist/test/unit/adapters/adapter-factory.test.d.ts.map +1 -0
  106. package/dist/test/unit/adapters/adapter-factory.test.js +147 -0
  107. package/dist/test/unit/adapters/adapter-factory.test.js.map +1 -0
  108. package/dist/test/unit/adapters/linux-adapter.test.d.ts +2 -0
  109. package/dist/test/unit/adapters/linux-adapter.test.d.ts.map +1 -0
  110. package/dist/test/unit/adapters/linux-adapter.test.js +191 -0
  111. package/dist/test/unit/adapters/linux-adapter.test.js.map +1 -0
  112. package/dist/test/unit/adapters/macos-adapter.test.d.ts +2 -0
  113. package/dist/test/unit/adapters/macos-adapter.test.d.ts.map +1 -0
  114. package/dist/test/unit/adapters/macos-adapter.test.js +224 -0
  115. package/dist/test/unit/adapters/macos-adapter.test.js.map +1 -0
  116. package/dist/test/unit/adapters/windows-adapter.test.d.ts +2 -0
  117. package/dist/test/unit/adapters/windows-adapter.test.d.ts.map +1 -0
  118. package/dist/test/unit/adapters/windows-adapter.test.js +41 -0
  119. package/dist/test/unit/adapters/windows-adapter.test.js.map +1 -0
  120. package/dist/test/unit/core/base-monitor.test.d.ts +2 -0
  121. package/dist/test/unit/core/base-monitor.test.d.ts.map +1 -0
  122. package/dist/test/unit/core/base-monitor.test.js +157 -0
  123. package/dist/test/unit/core/base-monitor.test.js.map +1 -0
  124. package/dist/test/unit/core/cache-manager.test.d.ts +6 -0
  125. package/dist/test/unit/core/cache-manager.test.d.ts.map +1 -0
  126. package/dist/test/unit/core/cache-manager.test.js +127 -0
  127. package/dist/test/unit/core/cache-manager.test.js.map +1 -0
  128. package/dist/test/unit/core/platform-adapter.test.d.ts +2 -0
  129. package/dist/test/unit/core/platform-adapter.test.d.ts.map +1 -0
  130. package/dist/test/unit/core/platform-adapter.test.js +186 -0
  131. package/dist/test/unit/core/platform-adapter.test.js.map +1 -0
  132. package/dist/test/unit/index.test.d.ts +2 -0
  133. package/dist/test/unit/index.test.d.ts.map +1 -0
  134. package/dist/test/unit/index.test.js +183 -0
  135. package/dist/test/unit/index.test.js.map +1 -0
  136. package/dist/test/unit/monitors/cpu-monitor.test.d.ts +2 -0
  137. package/dist/test/unit/monitors/cpu-monitor.test.d.ts.map +1 -0
  138. package/dist/test/unit/monitors/cpu-monitor.test.js +166 -0
  139. package/dist/test/unit/monitors/cpu-monitor.test.js.map +1 -0
  140. package/dist/test/unit/monitors/disk-monitor.test.d.ts +2 -0
  141. package/dist/test/unit/monitors/disk-monitor.test.d.ts.map +1 -0
  142. package/dist/test/unit/monitors/disk-monitor.test.js +46 -0
  143. package/dist/test/unit/monitors/disk-monitor.test.js.map +1 -0
  144. package/dist/test/unit/monitors/memory-monitor.test.d.ts +2 -0
  145. package/dist/test/unit/monitors/memory-monitor.test.d.ts.map +1 -0
  146. package/dist/test/unit/monitors/memory-monitor.test.js +142 -0
  147. package/dist/test/unit/monitors/memory-monitor.test.js.map +1 -0
  148. package/dist/test/unit/monitors/network-monitor.test.d.ts +2 -0
  149. package/dist/test/unit/monitors/network-monitor.test.d.ts.map +1 -0
  150. package/dist/test/unit/monitors/network-monitor.test.js +22 -0
  151. package/dist/test/unit/monitors/network-monitor.test.js.map +1 -0
  152. package/dist/test/unit/monitors/process-monitor.test.d.ts +2 -0
  153. package/dist/test/unit/monitors/process-monitor.test.d.ts.map +1 -0
  154. package/dist/test/unit/monitors/process-monitor.test.js +165 -0
  155. package/dist/test/unit/monitors/process-monitor.test.js.map +1 -0
  156. package/dist/test/unit/monitors/system-monitor-macos.test.d.ts +2 -0
  157. package/dist/test/unit/monitors/system-monitor-macos.test.d.ts.map +1 -0
  158. package/dist/test/unit/monitors/system-monitor-macos.test.js +115 -0
  159. package/dist/test/unit/monitors/system-monitor-macos.test.js.map +1 -0
  160. package/dist/test/unit/monitors/system-monitor.test.d.ts +2 -0
  161. package/dist/test/unit/monitors/system-monitor.test.d.ts.map +1 -0
  162. package/dist/test/unit/monitors/system-monitor.test.js +70 -0
  163. package/dist/test/unit/monitors/system-monitor.test.js.map +1 -0
  164. package/dist/test/unit/types/common.test.d.ts +6 -0
  165. package/dist/test/unit/types/common.test.d.ts.map +1 -0
  166. package/dist/test/unit/types/common.test.js +139 -0
  167. package/dist/test/unit/types/common.test.js.map +1 -0
  168. package/dist/test/unit/types/config.test.d.ts +2 -0
  169. package/dist/test/unit/types/config.test.d.ts.map +1 -0
  170. package/dist/test/unit/types/config.test.js +9 -0
  171. package/dist/test/unit/types/config.test.js.map +1 -0
  172. package/dist/test/unit/types/errors.test.d.ts +6 -0
  173. package/dist/test/unit/types/errors.test.d.ts.map +1 -0
  174. package/dist/test/unit/types/errors.test.js +184 -0
  175. package/dist/test/unit/types/errors.test.js.map +1 -0
  176. package/dist/test/unit/types/index.test.d.ts +2 -0
  177. package/dist/test/unit/types/index.test.d.ts.map +1 -0
  178. package/dist/test/unit/types/index.test.js +39 -0
  179. package/dist/test/unit/types/index.test.js.map +1 -0
  180. package/dist/test/unit/types/monitors.test.d.ts +2 -0
  181. package/dist/test/unit/types/monitors.test.d.ts.map +1 -0
  182. package/dist/test/unit/types/monitors.test.js +9 -0
  183. package/dist/test/unit/types/monitors.test.js.map +1 -0
  184. package/dist/test/unit/types/platform.test.d.ts +2 -0
  185. package/dist/test/unit/types/platform.test.d.ts.map +1 -0
  186. package/dist/test/unit/types/platform.test.js +9 -0
  187. package/dist/test/unit/types/platform.test.js.map +1 -0
  188. package/dist/test/unit/utils/command-executor.test.d.ts +6 -0
  189. package/dist/test/unit/utils/command-executor.test.d.ts.map +1 -0
  190. package/dist/test/unit/utils/command-executor.test.js +153 -0
  191. package/dist/test/unit/utils/command-executor.test.js.map +1 -0
  192. package/dist/test/unit/utils/platform-specific.test.d.ts +2 -0
  193. package/dist/test/unit/utils/platform-specific.test.d.ts.map +1 -0
  194. package/dist/test/unit/utils/platform-specific.test.js +32 -0
  195. package/dist/test/unit/utils/platform-specific.test.js.map +1 -0
  196. package/dist/test/utils/platform-specific.d.ts +139 -0
  197. package/dist/test/utils/platform-specific.d.ts.map +1 -0
  198. package/dist/test/utils/platform-specific.js +306 -0
  199. package/dist/test/utils/platform-specific.js.map +1 -0
  200. package/dist/test/utils/test-base.d.ts +157 -0
  201. package/dist/test/utils/test-base.d.ts.map +1 -0
  202. package/dist/test/utils/test-base.js +316 -0
  203. package/dist/test/utils/test-base.js.map +1 -0
  204. package/package.json +78 -18
  205. package/.travis.yml +0 -7
  206. package/index.js +0 -17
  207. package/lib/bucket.js +0 -14
  208. package/lib/cpu.js +0 -94
  209. package/lib/drive.js +0 -113
  210. package/lib/exec.js +0 -28
  211. package/lib/mem.js +0 -176
  212. package/lib/netstat.js +0 -182
  213. package/lib/openfiles.js +0 -25
  214. package/lib/os.js +0 -148
  215. package/lib/osCmd.js +0 -20
  216. package/lib/proc.js +0 -38
  217. package/lib/users.js +0 -18
  218. package/test/test.js +0 -55
  219. package/util/co.js +0 -237
  220. package/util/index.js +0 -12
@@ -0,0 +1,1144 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MacOSAdapter = void 0;
7
+ const os_1 = __importDefault(require("os"));
8
+ const platform_adapter_1 = require("../core/platform-adapter");
9
+ const command_executor_1 = require("../utils/command-executor");
10
+ const errors_1 = require("../types/errors");
11
+ /**
12
+ * macOS 平台适配器
13
+ *
14
+ * 实现 macOS 系统的监控功能,主要通过 sysctl、vm_stat、system_profiler 等命令
15
+ */
16
+ class MacOSAdapter extends platform_adapter_1.BasePlatformAdapter {
17
+ constructor() {
18
+ super('darwin');
19
+ this.executor = new command_executor_1.CommandExecutor('darwin');
20
+ }
21
+ /**
22
+ * 执行系统命令
23
+ */
24
+ async executeCommand(command, options) {
25
+ return this.executor.execute(command, options);
26
+ }
27
+ /**
28
+ * 读取文件内容,捕获并转换常见的权限/不存在错误
29
+ */
30
+ async readFile(path) {
31
+ try {
32
+ const result = await this.executeCommand(`cat "${path}"`);
33
+ this.validateCommandResult(result, `cat ${path}`);
34
+ return result.stdout;
35
+ }
36
+ catch (error) {
37
+ const err = error;
38
+ const errorCode = err?.code === 'EACCES'
39
+ ? errors_1.ErrorCode.PERMISSION_DENIED
40
+ : err?.code === 'ENOENT'
41
+ ? errors_1.ErrorCode.FILE_NOT_FOUND
42
+ : errors_1.ErrorCode.COMMAND_FAILED;
43
+ throw new errors_1.MonitorError(`Failed to read file: ${path}`, errorCode, this.platformName, { path, error: err?.message, code: err?.code });
44
+ }
45
+ }
46
+ /**
47
+ * 检查文件是否存在
48
+ */
49
+ async fileExists(path) {
50
+ try {
51
+ const result = await this.executeCommand(`test -f "${path}"`);
52
+ return result.exitCode === 0;
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ /**
59
+ * 通过 sysctl 汇总 CPU 基本信息
60
+ */
61
+ async getCPUInfo() {
62
+ try {
63
+ const [brand, cores, threads, freq] = await Promise.allSettled([
64
+ this.executeCommand('sysctl -n machdep.cpu.brand_string'),
65
+ this.executeCommand('sysctl -n hw.physicalcpu'),
66
+ this.executeCommand('sysctl -n hw.logicalcpu'),
67
+ this.executeCommand('sysctl -n hw.cpufrequency_max')
68
+ ]).then(results => [
69
+ results[0].status === 'fulfilled' ? results[0].value : null,
70
+ results[1].status === 'fulfilled' ? results[1].value : null,
71
+ results[2].status === 'fulfilled' ? results[2].value : null,
72
+ results[3].status === 'fulfilled' ? results[3].value : null
73
+ ]);
74
+ return this.parseCPUInfo(brand?.stdout || '', cores?.stdout || '', threads?.stdout || '', freq?.stdout || '');
75
+ }
76
+ catch (error) {
77
+ throw this.createCommandError('getCPUInfo', error);
78
+ }
79
+ }
80
+ /**
81
+ * 调用 top/iostat 获取 CPU 使用率,失败时链式回退
82
+ */
83
+ async getCPUUsage() {
84
+ try {
85
+ // 使用 top 命令获取 CPU 使用率
86
+ const result = await this.executeCommand('top -l 1 -n 0');
87
+ this.validateCommandResult(result, 'top command');
88
+ return this.parseCPUUsageFromTop(result.stdout);
89
+ }
90
+ catch (error) {
91
+ // 回退到 iostat
92
+ try {
93
+ const result = await this.executeCommand('iostat -c 1');
94
+ this.validateCommandResult(result, 'iostat command');
95
+ return this.parseCPUUsageFromIostat(result.stdout);
96
+ }
97
+ catch {
98
+ throw this.createCommandError('getCPUUsage', error);
99
+ }
100
+ }
101
+ }
102
+ /**
103
+ * 使用 powermetrics 读取温度,需要 sudo 权限
104
+ */
105
+ async getCPUTemperature() {
106
+ try {
107
+ // macOS 温度监控需要第三方工具或私有 API
108
+ // 尝试使用 powermetrics(需要 sudo)
109
+ const result = await this.executeCommand('powermetrics -n 1 -i 1000 --samplers smc');
110
+ return this.parseTemperatureFromPowermetrics(result.stdout);
111
+ }
112
+ catch (error) {
113
+ // 温度监控在 macOS 上可能需要额外权限
114
+ throw this.createUnsupportedError('cpu.temperature');
115
+ }
116
+ }
117
+ /**
118
+ * 读取 vm_stat 解析内存占用
119
+ */
120
+ async getMemoryInfo() {
121
+ try {
122
+ const [vmStat, totalMem, pressure] = await Promise.allSettled([
123
+ this.executeCommand('vm_stat'),
124
+ this.executeCommand('sysctl -n hw.memsize'),
125
+ this.executeCommand('memory_pressure')
126
+ ]).then(results => [
127
+ results[0].status === 'fulfilled' ? results[0].value : null,
128
+ results[1].status === 'fulfilled' ? results[1].value : null,
129
+ results[2].status === 'fulfilled' ? results[2].value : null
130
+ ]);
131
+ if (vmStat)
132
+ this.validateCommandResult(vmStat, 'vm_stat');
133
+ if (totalMem)
134
+ this.validateCommandResult(totalMem, 'sysctl hw.memsize');
135
+ return this.parseMemoryInfo(vmStat?.stdout || '', totalMem?.stdout || '', pressure?.stdout || '');
136
+ }
137
+ catch (error) {
138
+ throw this.createCommandError('getMemoryInfo', error);
139
+ }
140
+ }
141
+ /**
142
+ * 读取 vm_stat 解析内存占用
143
+ */
144
+ async getMemoryUsage() {
145
+ // macOS 上内存信息和使用情况来自相同来源
146
+ return this.getMemoryInfo();
147
+ }
148
+ /**
149
+ * 读取 df -h 解析磁盘占用
150
+ */
151
+ async getDiskInfo() {
152
+ try {
153
+ const result = await this.executeCommand('df -h');
154
+ this.validateCommandResult(result, 'df -h');
155
+ return this.parseDiskInfo(result.stdout);
156
+ }
157
+ catch (error) {
158
+ throw this.createCommandError('getDiskInfo', error);
159
+ }
160
+ }
161
+ /**
162
+ * 读取 iostat -d 解析磁盘 I/O 统计
163
+ */
164
+ async getDiskIO() {
165
+ try {
166
+ const result = await this.executeCommand('iostat -d');
167
+ this.validateCommandResult(result, 'iostat -d');
168
+ return this.parseDiskIO(result.stdout);
169
+ }
170
+ catch (error) {
171
+ throw this.createCommandError('getDiskIO', error);
172
+ }
173
+ }
174
+ /**
175
+ * 读取 ifconfig 解析网络接口列表
176
+ */
177
+ async getNetworkInterfaces() {
178
+ try {
179
+ const result = await this.executeCommand('ifconfig');
180
+ this.validateCommandResult(result, 'ifconfig');
181
+ return this.parseNetworkInterfaces(result.stdout);
182
+ }
183
+ catch (error) {
184
+ throw this.createCommandError('getNetworkInterfaces', error);
185
+ }
186
+ }
187
+ /**
188
+ * 读取 netstat -ib 解析网络统计信息
189
+ */
190
+ async getNetworkStats() {
191
+ try {
192
+ const result = await this.executeCommand('netstat -ib');
193
+ this.validateCommandResult(result, 'netstat -ib');
194
+ return this.parseNetworkStats(result.stdout);
195
+ }
196
+ catch (error) {
197
+ throw this.createCommandError('getNetworkStats', error);
198
+ }
199
+ }
200
+ /**
201
+ * 读取 ps -axo pid=,ppid=,comm=,%cpu=,%mem=,rss=,stat=,user=,args= 解析进程列表
202
+ */
203
+ async getProcesses() {
204
+ try {
205
+ const result = await this.executeCommand('ps -axo pid=,ppid=,comm=,%cpu=,%mem=,rss=,stat=,user=,args=');
206
+ this.validateCommandResult(result, 'ps command');
207
+ return this.parseProcessList(result.stdout);
208
+ }
209
+ catch (error) {
210
+ throw this.createCommandError('getProcesses', error);
211
+ }
212
+ }
213
+ /**
214
+ * 读取 ps -p pid -o pid,ppid,command,pcpu,pmem,state,user,lstart 解析特定进程信息
215
+ */
216
+ async getProcessInfo(pid) {
217
+ try {
218
+ const [summaryResult, commandResult, startResult] = await Promise.all([
219
+ this.executeCommand(`ps -p ${pid} -o pid=,ppid=,rss=,pcpu=,pmem=,state=,user=`),
220
+ this.executeCommand(`ps -p ${pid} -o command=`),
221
+ this.executeCommand(`ps -p ${pid} -o lstart=`)
222
+ ]);
223
+ this.validateCommandResult(summaryResult, `ps summary ${pid}`);
224
+ this.validateCommandResult(commandResult, `ps command ${pid}`);
225
+ this.validateCommandResult(startResult, `ps lstart ${pid}`);
226
+ const summaryLine = summaryResult.stdout.split('\n').find(line => line.trim().length > 0) || '';
227
+ const commandLine = commandResult.stdout.split('\n').find(line => line.trim().length > 0) || '';
228
+ const lstartLine = startResult.stdout.split('\n').find(line => line.trim().length > 0) || '';
229
+ return this.parseProcessInfo({ summary: summaryLine, command: commandLine, start: lstartLine }, pid);
230
+ }
231
+ catch (error) {
232
+ throw this.createCommandError('getProcessInfo', error);
233
+ }
234
+ }
235
+ /**
236
+ * 读取 uname -a, uptime, sysctl -n vm.loadavg, sw_vers 解析系统信息
237
+ */
238
+ async getSystemInfo() {
239
+ try {
240
+ const [uname, uptime, loadavg, osVersion] = await Promise.allSettled([
241
+ this.executeCommand('uname -a'),
242
+ this.executeCommand('uptime'),
243
+ this.executeCommand('sysctl -n vm.loadavg'),
244
+ this.executeCommand('sw_vers')
245
+ ]).then(results => [
246
+ results[0].status === 'fulfilled' ? results[0].value : null,
247
+ results[1].status === 'fulfilled' ? results[1].value : null,
248
+ results[2].status === 'fulfilled' ? results[2].value : null,
249
+ results[3].status === 'fulfilled' ? results[3].value : null
250
+ ]);
251
+ return this.parseSystemInfo(uname?.stdout || '', uptime?.stdout || '', loadavg?.stdout || '', osVersion?.stdout || null);
252
+ }
253
+ catch (error) {
254
+ throw this.createCommandError('getSystemInfo', error);
255
+ }
256
+ }
257
+ /**
258
+ * 读取 sysctl -n vm.loadavg 解析系统负载
259
+ */
260
+ async getSystemLoad() {
261
+ try {
262
+ const result = await this.executeCommand('sysctl -n vm.loadavg');
263
+ this.validateCommandResult(result, 'sysctl vm.loadavg');
264
+ return this.parseLoadAverage(result.stdout);
265
+ }
266
+ catch (error) {
267
+ throw this.createCommandError('getSystemLoad', error);
268
+ }
269
+ }
270
+ /**
271
+ * 读取 sysctl -n vm.loadavg 解析系统负载
272
+ */
273
+ initializeSupportedFeatures() {
274
+ return {
275
+ cpu: {
276
+ info: true,
277
+ usage: true,
278
+ temperature: false, // 需要特殊权限
279
+ frequency: true,
280
+ cache: false,
281
+ perCore: false,
282
+ cores: true
283
+ },
284
+ memory: {
285
+ info: true,
286
+ usage: true,
287
+ swap: true,
288
+ pressure: true,
289
+ detailed: true,
290
+ virtual: true
291
+ },
292
+ disk: {
293
+ info: true,
294
+ io: true,
295
+ health: false,
296
+ smart: false,
297
+ filesystem: true,
298
+ usage: true,
299
+ stats: true,
300
+ mounts: true,
301
+ filesystems: true
302
+ },
303
+ network: {
304
+ interfaces: true,
305
+ stats: true,
306
+ connections: true,
307
+ bandwidth: false,
308
+ gateway: true
309
+ },
310
+ process: {
311
+ list: true,
312
+ details: true,
313
+ tree: false,
314
+ monitor: true,
315
+ info: true,
316
+ kill: true,
317
+ openFiles: true,
318
+ environment: true
319
+ },
320
+ system: {
321
+ info: true,
322
+ load: true,
323
+ uptime: true,
324
+ users: true,
325
+ services: false
326
+ }
327
+ };
328
+ }
329
+ // 私有解析方法,解析命令输出为结构化数据
330
+ parseCPUInfo(brand, cores, threads, freq) {
331
+ return {
332
+ model: brand.trim(),
333
+ manufacturer: brand.includes('Intel') ? 'Intel' : brand.includes('Apple') ? 'Apple' : 'Unknown',
334
+ architecture: 'Unknown',
335
+ cores: this.safeParseInt(cores.trim()),
336
+ threads: this.safeParseInt(threads.trim()),
337
+ baseFrequency: freq ? this.safeParseInt(freq.trim()) / 1000000 : 0, // 转换为 MHz
338
+ maxFrequency: freq ? this.safeParseInt(freq.trim()) / 1000000 : 0,
339
+ cache: {},
340
+ features: []
341
+ };
342
+ }
343
+ /**
344
+ * 解析 top 命令输出为 CPU 使用率
345
+ */
346
+ parseCPUUsageFromTop(output) {
347
+ const lines = output.split('\n');
348
+ const cpuLine = lines.find(line => line.includes('CPU usage:'));
349
+ if (!cpuLine) {
350
+ throw this.createParseError(output, 'CPU usage line not found in top output');
351
+ }
352
+ // 解析类似 "CPU usage: 10.81% user, 13.73% sys, 75.45% idle" 的行
353
+ const userMatch = cpuLine.match(/([\d.]+)%\s+user/);
354
+ const sysMatch = cpuLine.match(/([\d.]+)%\s+sys/);
355
+ const idleMatch = cpuLine.match(/([\d.]+)%\s+idle/);
356
+ const user = userMatch ? this.safeParseNumber(userMatch[1]) : 0;
357
+ const system = sysMatch ? this.safeParseNumber(sysMatch[1]) : 0;
358
+ const idle = idleMatch ? this.safeParseNumber(idleMatch[1]) : 0;
359
+ return {
360
+ overall: 100 - idle,
361
+ user,
362
+ system,
363
+ idle,
364
+ cores: []
365
+ };
366
+ }
367
+ /**
368
+ * 解析 iostat 命令输出为 CPU 使用率
369
+ */
370
+ parseCPUUsageFromIostat(output) {
371
+ const lines = output.split('\n');
372
+ const dataLine = lines[lines.length - 2]; // iostat 的最后一行数据
373
+ if (!dataLine) {
374
+ throw this.createParseError(output, 'No data line found in iostat output');
375
+ }
376
+ const fields = dataLine.trim().split(/\s+/);
377
+ if (fields.length >= 3) {
378
+ const user = this.safeParseNumber(fields[0]);
379
+ const system = this.safeParseNumber(fields[1]);
380
+ const idle = this.safeParseNumber(fields[2]);
381
+ return {
382
+ overall: 100 - idle,
383
+ user,
384
+ system,
385
+ idle,
386
+ cores: []
387
+ };
388
+ }
389
+ throw this.createParseError(output, 'Unable to parse iostat CPU data');
390
+ }
391
+ /**
392
+ * 解析 powermetrics 命令输出为温度
393
+ */
394
+ parseTemperatureFromPowermetrics(output) {
395
+ // powermetrics 输出解析(简化版)
396
+ const lines = output.split('\n');
397
+ const temperatures = [];
398
+ for (const line of lines) {
399
+ const tempMatch = line.match(/(\w+)\s+temperature:\s+([\d.]+)/);
400
+ if (tempMatch) {
401
+ temperatures.push({
402
+ sensor: tempMatch[1],
403
+ temperature: this.safeParseNumber(tempMatch[2])
404
+ });
405
+ }
406
+ }
407
+ return temperatures;
408
+ }
409
+ /**
410
+ * 解析 vm_stat 输出为内存信息
411
+ */
412
+ parseMemoryInfo(vmStat, totalMem, pressure) {
413
+ const total = this.safeParseInt(totalMem.trim());
414
+ // 解析 vm_stat 输出
415
+ const vmLines = vmStat.split('\n');
416
+ const pageSizeLine = vmLines.find(line => /page size of\s+\d+\s+bytes/i.test(line));
417
+ const pageSizeMatch = pageSizeLine ? pageSizeLine.match(/page size of\s+(\d+)\s+bytes/i) : null;
418
+ const detectedPageSize = pageSizeMatch && pageSizeMatch[1]
419
+ ? this.safeParseInt(pageSizeMatch[1])
420
+ : 0;
421
+ const pageSize = detectedPageSize > 0 ? detectedPageSize : 4096;
422
+ let free = 0, active = 0, inactive = 0, wired = 0, compressed = 0;
423
+ for (const line of vmLines) {
424
+ const match = line.match(/Pages\s+([\w\s]+):\s+(\d+)/);
425
+ if (match) {
426
+ const [, typeRaw, count] = match;
427
+ const type = typeRaw.trim().toLowerCase();
428
+ const bytes = this.safeParseInt(count) * pageSize;
429
+ switch (type) {
430
+ case 'free':
431
+ free = bytes;
432
+ break;
433
+ case 'active':
434
+ active = bytes;
435
+ break;
436
+ case 'inactive':
437
+ inactive = bytes;
438
+ break;
439
+ case 'wired':
440
+ case 'wired down':
441
+ wired = bytes;
442
+ break;
443
+ case 'compressed':
444
+ case 'occupied':
445
+ case 'occupied by compressor':
446
+ compressed = bytes;
447
+ break;
448
+ }
449
+ }
450
+ }
451
+ const used = active + wired + compressed;
452
+ const available = total - used;
453
+ return {
454
+ total,
455
+ used,
456
+ free,
457
+ available,
458
+ active,
459
+ inactive,
460
+ wired,
461
+ compressed,
462
+ usagePercentage: total > 0 ? (used / total) * 100 : 0,
463
+ pressure: this.parseMemoryPressure(pressure)
464
+ };
465
+ }
466
+ /**
467
+ * 解析 memory_pressure 输出为内存压力
468
+ */
469
+ parseMemoryPressure(pressure) {
470
+ if (!pressure) {
471
+ return { level: 'normal', score: 0 };
472
+ }
473
+ // 简化的内存压力解析
474
+ if (pressure.includes('critical')) {
475
+ return { level: 'critical', score: 90 };
476
+ }
477
+ else if (pressure.includes('warn')) {
478
+ return { level: 'high', score: 70 };
479
+ }
480
+ else {
481
+ return { level: 'normal', score: 10 };
482
+ }
483
+ }
484
+ /**
485
+ * 解析 df -h 输出为磁盘信息
486
+ */
487
+ parseDiskInfo(output) {
488
+ const lines = output.split('\n').filter(line => line.trim());
489
+ if (lines.length < 2)
490
+ return [];
491
+ const disks = [];
492
+ for (let i = 1; i < lines.length; i++) {
493
+ const fields = lines[i].split(/\s+/);
494
+ if (fields.length >= 9) {
495
+ const [filesystem, size, used, available, capacity, /* iused */ , /* ifree */ , /* iusedPercent */ , mountpoint] = fields;
496
+ disks.push({
497
+ filesystem,
498
+ mountpoint,
499
+ size: this.convertDfSizeToBytes(size),
500
+ used: this.convertDfSizeToBytes(used),
501
+ available: this.convertDfSizeToBytes(available),
502
+ usagePercentage: this.safeParseNumber(capacity.replace('%', ''))
503
+ });
504
+ }
505
+ }
506
+ return disks;
507
+ }
508
+ /**
509
+ * 解析 iostat -d 输出为磁盘 I/O 统计
510
+ */
511
+ parseDiskIO(output) {
512
+ return this.parseIostatDisks(output).map(item => ({
513
+ device: item.device,
514
+ kbPerTransfer: item.kbPerTransfer,
515
+ transfersPerSec: item.transfersPerSec,
516
+ mbPerSec: item.mbPerSec,
517
+ readSpeed: item.bytePerSec,
518
+ iops: item.transfersPerSec
519
+ }));
520
+ }
521
+ /**
522
+ * 解析 ifconfig 输出为网络接口列表
523
+ */
524
+ parseNetworkInterfaces(output) {
525
+ const interfaces = [];
526
+ const blocks = output.split(/\n(?=\w)/); // 按接口分割
527
+ for (const block of blocks) {
528
+ const lines = block.split('\n');
529
+ const interfaceLine = lines[0];
530
+ if (!interfaceLine)
531
+ continue;
532
+ const nameMatch = interfaceLine.match(/^(\w+):/);
533
+ if (!nameMatch)
534
+ continue;
535
+ const name = nameMatch[1];
536
+ const addresses = [];
537
+ let state = 'down';
538
+ let mtu = 0;
539
+ let macAddress = '';
540
+ for (const line of lines) {
541
+ // 状态检查
542
+ if (line.includes('<UP,')) {
543
+ state = 'up';
544
+ }
545
+ // MTU 检查
546
+ const mtuMatch = line.match(/mtu (\d+)/);
547
+ if (mtuMatch) {
548
+ mtu = this.safeParseInt(mtuMatch[1]);
549
+ }
550
+ // MAC 地址
551
+ const etherMatch = line.match(/ether\s+([0-9a-f:]+)/i);
552
+ if (etherMatch) {
553
+ macAddress = etherMatch[1].toLowerCase();
554
+ }
555
+ // IPv4 地址
556
+ const inetMatch = line.match(/inet\s+([^\s]+)/);
557
+ if (inetMatch) {
558
+ addresses.push({
559
+ address: inetMatch[1],
560
+ family: 'IPv4'
561
+ });
562
+ }
563
+ // IPv6 地址
564
+ const inet6Match = line.match(/inet6\s+([^\s]+)/);
565
+ if (inet6Match) {
566
+ addresses.push({
567
+ address: inet6Match[1],
568
+ family: 'IPv6'
569
+ });
570
+ }
571
+ }
572
+ interfaces.push({
573
+ name,
574
+ addresses,
575
+ state,
576
+ mtu,
577
+ internal: name === 'lo0',
578
+ mac: macAddress
579
+ });
580
+ }
581
+ return interfaces;
582
+ }
583
+ /**
584
+ * 解析 netstat -ib/-i 输出,兼容是否包含字节列两种格式
585
+ */
586
+ parseNetworkStats(output) {
587
+ const lines = output.split('\n').filter(line => line.trim());
588
+ if (lines.length === 0)
589
+ return [];
590
+ const header = lines[0].toLowerCase();
591
+ const stats = [];
592
+ for (let i = 1; i < lines.length; i++) {
593
+ const fields = lines[i].trim().split(/\s+/);
594
+ if (fields.length < 8)
595
+ continue;
596
+ const name = fields[0];
597
+ const mtu = this.safeParseInt(fields[1]);
598
+ if (header.includes('ibytes') && fields.length >= 11) {
599
+ const tail = fields.slice(-7);
600
+ if (tail.length < 7)
601
+ continue;
602
+ const [ipkts, ierrs, ibytes, opkts, oerrs, obytes, collisions] = tail;
603
+ stats.push({
604
+ interface: name,
605
+ mtu,
606
+ rxPackets: this.safeParseInt(ipkts),
607
+ rxErrors: this.safeParseInt(ierrs),
608
+ rxBytes: this.safeParseInt(ibytes),
609
+ txPackets: this.safeParseInt(opkts),
610
+ txErrors: this.safeParseInt(oerrs),
611
+ txBytes: this.safeParseInt(obytes),
612
+ collisions: this.safeParseInt(collisions)
613
+ });
614
+ continue;
615
+ }
616
+ const tail = fields.slice(-5);
617
+ if (tail.length < 5)
618
+ continue;
619
+ const [ipkts, ierrs, opkts, oerrs, collisions] = tail;
620
+ stats.push({
621
+ interface: name,
622
+ mtu,
623
+ rxPackets: this.safeParseInt(ipkts),
624
+ rxErrors: this.safeParseInt(ierrs),
625
+ rxBytes: 0,
626
+ txPackets: this.safeParseInt(opkts),
627
+ txErrors: this.safeParseInt(oerrs),
628
+ txBytes: 0,
629
+ collisions: this.safeParseInt(collisions)
630
+ });
631
+ }
632
+ return stats;
633
+ }
634
+ /**
635
+ * 解析 ps -axo pid=,ppid=,comm=,%cpu=,%mem=,rss=,stat=,user=,args= 输出为进程列表
636
+ */
637
+ parseProcessList(output) {
638
+ const lines = output.split('\n').filter(line => line.trim());
639
+ const processes = [];
640
+ for (const line of lines) {
641
+ const fields = line.trim().split(/\s+/);
642
+ if (fields.length >= 8) {
643
+ const [pid, ppid, cmd, pcpu, pmem, rss, state, user, ...argsParts] = fields;
644
+ const command = argsParts.length > 0 ? argsParts.join(' ').trim() : cmd;
645
+ processes.push({
646
+ pid: this.safeParseInt(pid),
647
+ ppid: this.safeParseInt(ppid),
648
+ name: cmd,
649
+ comm: cmd,
650
+ command,
651
+ cpuUsage: this.safeParseNumber(pcpu),
652
+ memoryUsage: this.safeParseInt(rss) * 1024,
653
+ memoryPercentage: this.safeParseNumber(pmem),
654
+ state,
655
+ user
656
+ });
657
+ }
658
+ }
659
+ return processes;
660
+ }
661
+ /**
662
+ * 解析 ps 输出的进程详细信息
663
+ */
664
+ parseProcessInfo(data, pid) {
665
+ const summaryParts = data.summary.trim().split(/\s+/);
666
+ if (summaryParts.length < 7) {
667
+ throw new errors_1.MonitorError(`Process ${pid} not found`, errors_1.ErrorCode.NOT_AVAILABLE, this.platformName, { pid });
668
+ }
669
+ const [pidStr, ppidStr, rssStr, pcpu, pmem, state, user] = summaryParts;
670
+ const command = data.command.trim();
671
+ const lstart = data.start.trim();
672
+ return {
673
+ pid: this.safeParseInt(pidStr) || pid,
674
+ ppid: this.safeParseInt(ppidStr),
675
+ name: command.split(' ')[0] || command,
676
+ command,
677
+ cpuUsage: this.safeParseNumber(pcpu),
678
+ memoryUsage: this.safeParseInt(rssStr) * 1024,
679
+ memoryPercentage: this.safeParseNumber(pmem),
680
+ state,
681
+ user,
682
+ startTime: lstart
683
+ };
684
+ }
685
+ /**
686
+ * 解析 uname -a, uptime, sysctl -n vm.loadavg, sw_vers 输出为系统信息
687
+ */
688
+ parseSystemInfo(uname, uptime, loadavg, osVersion) {
689
+ const unameFields = uname.trim().split(' ');
690
+ const uptimeSeconds = os_1.default.uptime();
691
+ const bootTime = Date.now() - uptimeSeconds * 1000;
692
+ const load = this.parseLoadAverage(loadavg);
693
+ const uptimeMs = uptimeSeconds * 1000;
694
+ return {
695
+ hostname: unameFields[1] || 'Unknown',
696
+ platform: 'darwin',
697
+ release: unameFields[2] || 'Unknown',
698
+ version: osVersion ? osVersion.trim() : unameFields[3] || 'Unknown',
699
+ arch: unameFields[4] || 'Unknown',
700
+ uptime: uptimeMs,
701
+ uptimeSeconds,
702
+ bootTime,
703
+ loadAverage: load
704
+ };
705
+ }
706
+ /**
707
+ * 解析 sysctl -n vm.loadavg 输出为系统负载
708
+ */
709
+ parseLoadAverage(output) {
710
+ const match = output.trim().match(/\{\s*([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*\}/);
711
+ if (match) {
712
+ return {
713
+ load1: this.safeParseNumber(match[1]),
714
+ load5: this.safeParseNumber(match[2]),
715
+ load15: this.safeParseNumber(match[3])
716
+ };
717
+ }
718
+ throw this.createParseError(output, 'Unable to parse load average');
719
+ }
720
+ /**
721
+ * 解析 df -h 输出的大小格式转换
722
+ */
723
+ convertDfSizeToBytes(sizeStr) {
724
+ // df -h 输出的大小格式转换
725
+ const match = sizeStr.match(/^([\d.]+)([KMGT]?)i?$/);
726
+ if (!match)
727
+ return 0;
728
+ const value = this.safeParseNumber(match[1]);
729
+ const unit = match[2];
730
+ const multipliers = {
731
+ '': 1024, // df 默认单位是 KB
732
+ 'K': 1024,
733
+ 'M': 1024 * 1024,
734
+ 'G': 1024 * 1024 * 1024,
735
+ 'T': 1024 * 1024 * 1024 * 1024
736
+ };
737
+ return value * (multipliers[unit] || 1024);
738
+ }
739
+ // 实现抽象方法,获取结构化数据
740
+ /**
741
+ * 获取磁盘使用情况,解析 df -k 输出为磁盘使用情况
742
+ */
743
+ async getDiskUsage() {
744
+ try {
745
+ const result = await this.executeCommand('df -k');
746
+ return this.parseDiskUsage(result.stdout);
747
+ }
748
+ catch (error) {
749
+ throw this.createCommandError('getDiskUsage', error);
750
+ }
751
+ }
752
+ /**
753
+ * 获取磁盘统计,解析 iostat -d 输出为磁盘统计
754
+ */
755
+ async getDiskStats() {
756
+ try {
757
+ const result = await this.executeCommand('iostat -d');
758
+ return this.parseDiskStats(result.stdout);
759
+ }
760
+ catch (error) {
761
+ throw this.createCommandError('getDiskStats', error);
762
+ }
763
+ }
764
+ /**
765
+ * 获取挂载点,解析 mount 输出为挂载点
766
+ */
767
+ async getMounts() {
768
+ try {
769
+ const result = await this.executeCommand('mount');
770
+ return this.parseMounts(result.stdout);
771
+ }
772
+ catch (error) {
773
+ throw this.createCommandError('getMounts', error);
774
+ }
775
+ }
776
+ /**
777
+ * 获取文件系统,解析 diskutil list 输出为文件系统
778
+ */
779
+ async getFileSystems() {
780
+ try {
781
+ const result = await this.executeCommand('diskutil list');
782
+ return this.parseFileSystems(result.stdout);
783
+ }
784
+ catch (error) {
785
+ throw this.createCommandError('getFileSystems', error);
786
+ }
787
+ }
788
+ /**
789
+ * 获取网络连接,解析 netstat -an 输出为网络连接
790
+ */
791
+ async getNetworkConnections() {
792
+ try {
793
+ const result = await this.executeCommand('netstat -an');
794
+ return this.parseNetworkConnections(result.stdout);
795
+ }
796
+ catch (error) {
797
+ throw this.createCommandError('getNetworkConnections', error);
798
+ }
799
+ }
800
+ /**
801
+ * 获取默认网关,解析 route -n get default 输出为默认网关
802
+ */
803
+ async getDefaultGateway() {
804
+ try {
805
+ const result = await this.executeCommand('route -n get default');
806
+ return this.parseDefaultGateway(result.stdout);
807
+ }
808
+ catch (error) {
809
+ throw this.createCommandError('getDefaultGateway', error);
810
+ }
811
+ }
812
+ /**
813
+ * 获取进程列表,解析 ps -axo pid=,ppid=,comm=,%cpu=,%mem=,rss=,stat=,user=,args= 输出为进程列表
814
+ */
815
+ async getProcessList() {
816
+ try {
817
+ const result = await this.executeCommand('ps -axo pid=,ppid=,comm=,%cpu=,%mem=,rss=,stat=,user=,args=');
818
+ return this.parseProcessList(result.stdout);
819
+ }
820
+ catch (error) {
821
+ throw this.createCommandError('getProcessList', error);
822
+ }
823
+ }
824
+ /**
825
+ * 杀死进程,解析 kill -${signal} ${pid} 输出为杀死进程
826
+ */
827
+ async killProcess(pid, signal = 'TERM') {
828
+ try {
829
+ const result = await this.executeCommand(`kill -${signal} ${pid}`);
830
+ return result.exitCode === 0;
831
+ }
832
+ catch (error) {
833
+ return false;
834
+ }
835
+ }
836
+ /**
837
+ * 获取进程打开文件,解析 lsof -p ${pid} +c0 -Fn 输出为进程打开文件
838
+ */
839
+ async getProcessOpenFiles(pid) {
840
+ try {
841
+ const result = await this.executeCommand(`lsof -p ${pid} +c0 -Fn`);
842
+ return this.parseOpenFiles(result.stdout);
843
+ }
844
+ catch (error) {
845
+ return [];
846
+ }
847
+ }
848
+ /**
849
+ * 获取进程环境变量,解析 ps eww ${pid} 输出为进程环境变量
850
+ */
851
+ async getProcessEnvironment(pid) {
852
+ try {
853
+ const result = await this.executeCommand(`ps eww ${pid}`);
854
+ return this.parseEnvironment(result.stdout);
855
+ }
856
+ catch (error) {
857
+ return {};
858
+ }
859
+ }
860
+ /**
861
+ * 获取系统运行时间
862
+ */
863
+ async getSystemUptime() {
864
+ try {
865
+ const uptimeSeconds = os_1.default.uptime();
866
+ return {
867
+ uptime: uptimeSeconds,
868
+ bootTime: Date.now() - uptimeSeconds * 1000
869
+ };
870
+ }
871
+ catch (error) {
872
+ throw this.createCommandError('getSystemUptime', error);
873
+ }
874
+ }
875
+ /**
876
+ * 获取系统用户,解析 who 输出为系统用户
877
+ */
878
+ async getSystemUsers() {
879
+ try {
880
+ const result = await this.executeCommand('who');
881
+ return this.parseSystemUsers(result.stdout);
882
+ }
883
+ catch (error) {
884
+ throw this.createCommandError('getSystemUsers', error);
885
+ }
886
+ }
887
+ /**
888
+ * 获取系统服务,解析 launchctl list 输出为系统服务
889
+ */
890
+ async getSystemServices() {
891
+ try {
892
+ const result = await this.executeCommand('launchctl list');
893
+ return this.parseSystemServices(result.stdout);
894
+ }
895
+ catch (error) {
896
+ throw this.createCommandError('getSystemServices', error);
897
+ }
898
+ }
899
+ // 私有解析方法,解析命令输出为结构化数据
900
+ parseDiskUsage(output) {
901
+ const lines = output.split('\n').slice(1); // 跳过标题行
902
+ const disks = [];
903
+ for (const line of lines) {
904
+ const fields = line.trim().split(/\s+/);
905
+ if (fields.length >= 9) {
906
+ const usedPercent = fields[4].replace('%', '');
907
+ disks.push({
908
+ device: fields[0],
909
+ total: this.safeParseInt(fields[1]) * 1024, // KB to bytes
910
+ used: this.safeParseInt(fields[2]) * 1024,
911
+ available: this.safeParseInt(fields[3]) * 1024,
912
+ usagePercentage: this.safeParseNumber(usedPercent),
913
+ mountPoint: fields[8]
914
+ });
915
+ }
916
+ }
917
+ return disks;
918
+ }
919
+ /**
920
+ * 解析 iostat -d 输出为磁盘统计
921
+ */
922
+ parseDiskStats(output) {
923
+ return this.parseIostatDisks(output).map(item => ({
924
+ device: item.device,
925
+ readBytes: item.bytePerSec,
926
+ writeBytes: 0,
927
+ readCount: item.transfersPerSec,
928
+ writeCount: 0,
929
+ readTime: 0,
930
+ writeTime: 0,
931
+ ioTime: 0,
932
+ readSpeed: item.bytePerSec,
933
+ writeSpeed: 0,
934
+ iops: item.transfersPerSec
935
+ }));
936
+ }
937
+ /**
938
+ * 解析 mount 输出为挂载点
939
+ */
940
+ parseMounts(output) {
941
+ const lines = output.split('\n').filter(line => line.trim());
942
+ const mounts = [];
943
+ for (const line of lines) {
944
+ const match = line.match(/^(.+?)\s+on\s+(.+?)\s+\((.+?)\)$/);
945
+ if (match) {
946
+ const [, device, mountPoint, options] = match;
947
+ const optionsArray = options.split(',').map(opt => opt.trim());
948
+ mounts.push({
949
+ device: device.trim(),
950
+ mountPoint: mountPoint.trim(),
951
+ filesystem: optionsArray[0] || 'unknown',
952
+ options: optionsArray,
953
+ dump: 0,
954
+ pass: 0
955
+ });
956
+ }
957
+ }
958
+ return mounts;
959
+ }
960
+ /**
961
+ * 解析 diskutil list 输出为文件系统
962
+ */
963
+ parseFileSystems(output) {
964
+ const lines = output.split('\n').filter(line => line.trim());
965
+ const filesystems = [];
966
+ for (const line of lines) {
967
+ if (line.includes('GUID_partition_scheme') || line.includes('Apple_HFS') ||
968
+ line.includes('Apple_APFS') || line.includes('Microsoft Basic Data')) {
969
+ const parts = line.trim().split(/\s+/);
970
+ if (parts.length >= 3) {
971
+ filesystems.push({
972
+ name: parts[2] || 'unknown',
973
+ type: parts[1] || 'unknown',
974
+ supported: true
975
+ });
976
+ }
977
+ }
978
+ }
979
+ return filesystems;
980
+ }
981
+ /**
982
+ * 解析 netstat -an 输出为网络连接
983
+ */
984
+ parseNetworkConnections(output) {
985
+ const lines = output.split('\n').filter(line => line.trim());
986
+ const connections = [];
987
+ for (const line of lines) {
988
+ const fields = line.trim().split(/\s+/);
989
+ if (fields.length >= 6 && (fields[0].includes('tcp') || fields[0].includes('udp'))) {
990
+ connections.push({
991
+ protocol: fields[0],
992
+ localAddress: fields[3] || '*',
993
+ foreignAddress: fields[4] || '*',
994
+ state: fields[5] || 'unknown'
995
+ });
996
+ }
997
+ }
998
+ return connections;
999
+ }
1000
+ /**
1001
+ * 解析 route -n get default 输出为默认网关
1002
+ */
1003
+ parseDefaultGateway(output) {
1004
+ const lines = output.split('\n');
1005
+ let gateway = null;
1006
+ let interfaceName = null;
1007
+ for (const line of lines) {
1008
+ if (line.includes('gateway:')) {
1009
+ const match = line.match(/gateway:\s*(.+)/);
1010
+ if (match)
1011
+ gateway = match[1].trim();
1012
+ }
1013
+ if (line.includes('interface:')) {
1014
+ const match = line.match(/interface:\s*(.+)/);
1015
+ if (match)
1016
+ interfaceName = match[1].trim();
1017
+ }
1018
+ }
1019
+ return gateway ? { gateway, interface: interfaceName || 'unknown' } : null;
1020
+ }
1021
+ /**
1022
+ * 解析 lsof -p ${pid} +c0 -Fn 输出为进程打开文件
1023
+ */
1024
+ parseOpenFiles(output) {
1025
+ const lines = output.split('\n');
1026
+ const files = [];
1027
+ for (const line of lines) {
1028
+ if (line.startsWith('n')) {
1029
+ files.push(line.substring(1));
1030
+ }
1031
+ }
1032
+ return files;
1033
+ }
1034
+ /**
1035
+ * 解析 ps eww ${pid} 输出为进程环境变量
1036
+ */
1037
+ parseEnvironment(output) {
1038
+ const env = {};
1039
+ if (!output) {
1040
+ return env;
1041
+ }
1042
+ const pattern = /(^|\s)([A-Za-z_][A-Za-z0-9_]*)=([\s\S]*?)(?=(\s+[A-Za-z_][A-Za-z0-9_]*=)|$)/g;
1043
+ let match;
1044
+ while ((match = pattern.exec(output)) !== null) {
1045
+ const key = match[2];
1046
+ if (key === 'PID') {
1047
+ continue;
1048
+ }
1049
+ const value = match[3].replace(/\s+$/u, '');
1050
+ env[key] = value;
1051
+ }
1052
+ return env;
1053
+ }
1054
+ parseIostatDisks(output) {
1055
+ const lines = output.split('\n').map(line => line.trimEnd());
1056
+ const deviceLineIndex = lines.findIndex(line => /disk\w+/i.test(line));
1057
+ if (deviceLineIndex === -1) {
1058
+ return [];
1059
+ }
1060
+ const deviceLine = lines[deviceLineIndex];
1061
+ const deviceNames = (deviceLine.match(/disk[^\s]*/gi) || []).map(name => name.trim());
1062
+ if (deviceNames.length === 0) {
1063
+ return [];
1064
+ }
1065
+ const dataLines = lines.slice(deviceLineIndex + 1).filter(line => line && /[\d.]/.test(line));
1066
+ if (dataLines.length === 0) {
1067
+ return [];
1068
+ }
1069
+ const tokens = dataLines[0].trim().split(/\s+/);
1070
+ const metricsPerDevice = 3;
1071
+ const result = [];
1072
+ deviceNames.forEach((device, index) => {
1073
+ const offset = index * metricsPerDevice;
1074
+ if (tokens.length >= offset + metricsPerDevice) {
1075
+ const kbPerTransfer = this.safeParseNumber(tokens[offset]);
1076
+ const transfersPerSec = this.safeParseNumber(tokens[offset + 1]);
1077
+ const mbPerSec = this.safeParseNumber(tokens[offset + 2]);
1078
+ const bytePerSec = mbPerSec * 1024 * 1024;
1079
+ result.push({
1080
+ device,
1081
+ kbPerTransfer,
1082
+ transfersPerSec,
1083
+ mbPerSec,
1084
+ bytePerSec
1085
+ });
1086
+ }
1087
+ });
1088
+ return result;
1089
+ }
1090
+ /**
1091
+ * 解析 uptime 输出为系统运行时间
1092
+ */
1093
+ parseSystemUptime(output) {
1094
+ const uptimeMatch = output.match(/up\s+(.+?),/);
1095
+ const loadMatch = output.match(/load averages:\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)/);
1096
+ return {
1097
+ uptime: uptimeMatch ? uptimeMatch[1].trim() : 'unknown',
1098
+ loadAverage: loadMatch ? {
1099
+ load1: this.safeParseNumber(loadMatch[1]),
1100
+ load5: this.safeParseNumber(loadMatch[2]),
1101
+ load15: this.safeParseNumber(loadMatch[3])
1102
+ } : { load1: 0, load5: 0, load15: 0 }
1103
+ };
1104
+ }
1105
+ /**
1106
+ * 解析 who 输出为系统用户
1107
+ */
1108
+ parseSystemUsers(output) {
1109
+ const lines = output.split('\n').filter(line => line.trim());
1110
+ const users = [];
1111
+ for (const line of lines) {
1112
+ const fields = line.trim().split(/\s+/);
1113
+ if (fields.length >= 5) {
1114
+ users.push({
1115
+ user: fields[0],
1116
+ terminal: fields[1],
1117
+ loginTime: fields.slice(2, -1).join(' '),
1118
+ from: fields[fields.length - 1]
1119
+ });
1120
+ }
1121
+ }
1122
+ return users;
1123
+ }
1124
+ /**
1125
+ * 解析 launchctl list 输出为系统服务
1126
+ */
1127
+ parseSystemServices(output) {
1128
+ const lines = output.split('\n').slice(1); // 跳过标题行
1129
+ const services = [];
1130
+ for (const line of lines) {
1131
+ const fields = line.trim().split(/\s+/);
1132
+ if (fields.length >= 3) {
1133
+ services.push({
1134
+ pid: fields[0] === '-' ? null : this.safeParseInt(fields[0]),
1135
+ status: fields[1],
1136
+ label: fields[2]
1137
+ });
1138
+ }
1139
+ }
1140
+ return services;
1141
+ }
1142
+ }
1143
+ exports.MacOSAdapter = MacOSAdapter;
1144
+ //# sourceMappingURL=macos-adapter.js.map