mcp-log-query-server 3.4.0 → 3.4.1
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.
- package/package.json +1 -1
- package/ssh-client.js +35 -69
package/package.json
CHANGED
package/ssh-client.js
CHANGED
|
@@ -34,32 +34,35 @@ export async function queryLog(service, command, options = {}) {
|
|
|
34
34
|
let kubectlOutput = '';
|
|
35
35
|
let collectingOutput = false;
|
|
36
36
|
|
|
37
|
-
// 设置超时
|
|
37
|
+
// 设置超时 - 使用 destroy() 强制关闭
|
|
38
|
+
let settled = false;
|
|
38
39
|
timeoutId = setTimeout(() => {
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
if (!settled) {
|
|
41
|
+
settled = true;
|
|
42
|
+
try { conn.destroy(); } catch {};
|
|
43
|
+
reject(new Error(`命令执行超时 (${timeout}ms)`));
|
|
44
|
+
}
|
|
41
45
|
}, timeout);
|
|
42
46
|
|
|
43
47
|
conn.on('ready', () => {
|
|
44
|
-
console.error('[SSH] 已连接到堡垒机');
|
|
45
|
-
|
|
46
48
|
conn.shell({ term: 'xterm', rows: 24, cols: 500 }, (err, stream) => {
|
|
47
49
|
if (err) {
|
|
48
50
|
clearTimeout(timeoutId);
|
|
49
|
-
reject(err);
|
|
51
|
+
if (!settled) { settled = true; reject(err); }
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
stream.on('close', () => {
|
|
54
56
|
clearTimeout(timeoutId);
|
|
55
|
-
conn.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
try { conn.destroy(); } catch {}
|
|
58
|
+
if (!settled) {
|
|
59
|
+
settled = true;
|
|
60
|
+
resolve(cleanTerminalOutput(kubectlOutput || buffer));
|
|
61
|
+
}
|
|
60
62
|
});
|
|
61
63
|
|
|
62
64
|
stream.on('data', (data) => {
|
|
65
|
+
if (settled) return; // 已超时,忽略后续数据
|
|
63
66
|
const text = data.toString();
|
|
64
67
|
buffer += text;
|
|
65
68
|
|
|
@@ -67,64 +70,43 @@ export async function queryLog(service, command, options = {}) {
|
|
|
67
70
|
kubectlOutput += text;
|
|
68
71
|
}
|
|
69
72
|
|
|
70
|
-
// JumpServer 状态机
|
|
71
|
-
|
|
72
|
-
// 阶段1: 等待 Opt> 提示符
|
|
73
|
+
// JumpServer 状态机
|
|
73
74
|
if (stage === 'init' && buffer.includes('Opt>')) {
|
|
74
75
|
stage = 'opt';
|
|
75
|
-
console.error('[SSH] 输入目标服务器 IP');
|
|
76
76
|
stream.write(K8S_SERVER.host + '\r');
|
|
77
77
|
}
|
|
78
|
-
// 阶段2: 等待 [Host]> 提示符(搜索结果列表后)
|
|
79
78
|
else if (stage === 'opt' && buffer.includes('[Host]>')) {
|
|
80
79
|
stage = 'host';
|
|
81
|
-
console.error('[SSH] 选择服务器 ID: ' + K8S_SERVER.selectOption);
|
|
82
80
|
stream.write(K8S_SERVER.selectOption + '\r');
|
|
83
81
|
}
|
|
84
|
-
// 阶段3: 等待进入服务器 shell(检测 ~]$ 或 ~]# 提示符)
|
|
85
82
|
else if (stage === 'host' && (buffer.includes('~]$') || buffer.includes('~]#'))) {
|
|
86
83
|
stage = 'server';
|
|
87
|
-
console.error('[SSH] 已进入服务器,执行 kubectl 命令');
|
|
88
|
-
|
|
89
|
-
// 构建并执行 kubectl 命令
|
|
90
84
|
const kubectlCmd = buildKubectlCommand(service, command);
|
|
91
|
-
console.error(`[SSH] 命令: ${kubectlCmd.substring(0, 80)}...`);
|
|
92
|
-
|
|
93
|
-
// 重置 buffer,开始收集 kubectl 输出
|
|
94
85
|
kubectlOutput = '';
|
|
95
86
|
collectingOutput = true;
|
|
96
|
-
|
|
97
87
|
stream.write(kubectlCmd + '\r');
|
|
98
88
|
stage = 'kubectl';
|
|
99
89
|
}
|
|
100
|
-
// 阶段4: kubectl 执行完成
|
|
101
90
|
else if (stage === 'kubectl' && collectingOutput && kubectlOutput.length > 50) {
|
|
102
|
-
// 检测命令执行完成(返回到 shell 提示符)
|
|
103
91
|
if (kubectlOutput.includes('~]$') || kubectlOutput.includes('~]#')) {
|
|
104
92
|
stage = 'done';
|
|
105
93
|
collectingOutput = false;
|
|
106
|
-
console.error('[SSH] 命令执行完成,退出');
|
|
107
|
-
|
|
108
|
-
// 立即退出
|
|
109
94
|
stream.write('exit\r');
|
|
110
95
|
stream.write('exit\r');
|
|
111
|
-
setTimeout(() => stream.end(),
|
|
96
|
+
setTimeout(() => { try { stream.end(); } catch {} }, 300);
|
|
112
97
|
}
|
|
113
98
|
}
|
|
114
99
|
});
|
|
115
100
|
|
|
116
|
-
stream.stderr.on('data', (
|
|
117
|
-
console.error('[SSH stderr]', data.toString());
|
|
118
|
-
});
|
|
101
|
+
stream.stderr.on('data', () => {});
|
|
119
102
|
});
|
|
120
103
|
});
|
|
121
104
|
|
|
122
105
|
conn.on('error', (err) => {
|
|
123
106
|
clearTimeout(timeoutId);
|
|
124
|
-
reject(new Error(`SSH 连接错误: ${err.message}`));
|
|
107
|
+
if (!settled) { settled = true; reject(new Error(`SSH 连接错误: ${err.message}`)); }
|
|
125
108
|
});
|
|
126
109
|
|
|
127
|
-
// 连接堡垒机
|
|
128
110
|
conn.connect({
|
|
129
111
|
host: JUMP_HOST.host,
|
|
130
112
|
port: JUMP_HOST.port,
|
|
@@ -227,32 +209,35 @@ export async function executeKubectl(kubectlCommand, options = {}) {
|
|
|
227
209
|
let kubectlOutput = '';
|
|
228
210
|
let collectingOutput = false;
|
|
229
211
|
|
|
230
|
-
// 设置超时
|
|
212
|
+
// 设置超时 - 使用 destroy() 强制关闭
|
|
213
|
+
let settled = false;
|
|
231
214
|
timeoutId = setTimeout(() => {
|
|
232
|
-
|
|
233
|
-
|
|
215
|
+
if (!settled) {
|
|
216
|
+
settled = true;
|
|
217
|
+
try { conn.destroy(); } catch {}
|
|
218
|
+
reject(new Error(`命令执行超时 (${timeout}ms)`));
|
|
219
|
+
}
|
|
234
220
|
}, timeout);
|
|
235
221
|
|
|
236
222
|
conn.on('ready', () => {
|
|
237
|
-
console.error('[SSH] 已连接到堡垒机');
|
|
238
|
-
|
|
239
223
|
conn.shell({ term: 'xterm', rows: 24, cols: 500 }, (err, stream) => {
|
|
240
224
|
if (err) {
|
|
241
225
|
clearTimeout(timeoutId);
|
|
242
|
-
reject(err);
|
|
226
|
+
if (!settled) { settled = true; reject(err); }
|
|
243
227
|
return;
|
|
244
228
|
}
|
|
245
229
|
|
|
246
230
|
stream.on('close', () => {
|
|
247
231
|
clearTimeout(timeoutId);
|
|
248
|
-
conn.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
232
|
+
try { conn.destroy(); } catch {}
|
|
233
|
+
if (!settled) {
|
|
234
|
+
settled = true;
|
|
235
|
+
resolve(cleanTerminalOutput(kubectlOutput || buffer));
|
|
236
|
+
}
|
|
253
237
|
});
|
|
254
238
|
|
|
255
239
|
stream.on('data', (data) => {
|
|
240
|
+
if (settled) return;
|
|
256
241
|
const text = data.toString();
|
|
257
242
|
buffer += text;
|
|
258
243
|
|
|
@@ -261,60 +246,41 @@ export async function executeKubectl(kubectlCommand, options = {}) {
|
|
|
261
246
|
}
|
|
262
247
|
|
|
263
248
|
// JumpServer 状态机
|
|
264
|
-
|
|
265
|
-
// 阶段1: 等待 Opt> 提示符
|
|
266
249
|
if (stage === 'init' && buffer.includes('Opt>')) {
|
|
267
250
|
stage = 'opt';
|
|
268
|
-
console.error('[SSH] 输入目标服务器 IP');
|
|
269
251
|
stream.write(K8S_SERVER.host + '\r');
|
|
270
252
|
}
|
|
271
|
-
// 阶段2: 等待 [Host]> 提示符
|
|
272
253
|
else if (stage === 'opt' && buffer.includes('[Host]>')) {
|
|
273
254
|
stage = 'host';
|
|
274
|
-
console.error('[SSH] 选择服务器 ID: ' + K8S_SERVER.selectOption);
|
|
275
255
|
stream.write(K8S_SERVER.selectOption + '\r');
|
|
276
256
|
}
|
|
277
|
-
// 阶段3: 等待进入服务器 shell
|
|
278
257
|
else if (stage === 'host' && (buffer.includes('~]$') || buffer.includes('~]#'))) {
|
|
279
258
|
stage = 'server';
|
|
280
|
-
console.error('[SSH] 已进入服务器,执行 kubectl 命令');
|
|
281
|
-
console.error(`[SSH] 命令: ${kubectlCommand.substring(0, 100)}...`);
|
|
282
|
-
|
|
283
|
-
// 重置 buffer,开始收集 kubectl 输出
|
|
284
259
|
kubectlOutput = '';
|
|
285
260
|
collectingOutput = true;
|
|
286
|
-
|
|
287
261
|
stream.write(kubectlCommand + '\r');
|
|
288
262
|
stage = 'kubectl';
|
|
289
263
|
}
|
|
290
|
-
// 阶段4: kubectl 执行完成
|
|
291
264
|
else if (stage === 'kubectl' && collectingOutput && kubectlOutput.length > 50) {
|
|
292
|
-
// 检测命令执行完成(返回到 shell 提示符)
|
|
293
265
|
if (kubectlOutput.includes('~]$') || kubectlOutput.includes('~]#')) {
|
|
294
266
|
stage = 'done';
|
|
295
267
|
collectingOutput = false;
|
|
296
|
-
console.error('[SSH] 命令执行完成,退出');
|
|
297
|
-
|
|
298
|
-
// 立即退出
|
|
299
268
|
stream.write('exit\r');
|
|
300
269
|
stream.write('exit\r');
|
|
301
|
-
setTimeout(() => stream.end(),
|
|
270
|
+
setTimeout(() => { try { stream.end(); } catch {} }, 300);
|
|
302
271
|
}
|
|
303
272
|
}
|
|
304
273
|
});
|
|
305
274
|
|
|
306
|
-
stream.stderr.on('data', (
|
|
307
|
-
console.error('[SSH stderr]', data.toString());
|
|
308
|
-
});
|
|
275
|
+
stream.stderr.on('data', () => {});
|
|
309
276
|
});
|
|
310
277
|
});
|
|
311
278
|
|
|
312
279
|
conn.on('error', (err) => {
|
|
313
280
|
clearTimeout(timeoutId);
|
|
314
|
-
reject(new Error(`SSH 连接错误: ${err.message}`));
|
|
281
|
+
if (!settled) { settled = true; reject(new Error(`SSH 连接错误: ${err.message}`)); }
|
|
315
282
|
});
|
|
316
283
|
|
|
317
|
-
// 连接堡垒机
|
|
318
284
|
conn.connect({
|
|
319
285
|
host: JUMP_HOST.host,
|
|
320
286
|
port: JUMP_HOST.port,
|