@hyzyn/dsh-tty 0.20.2 → 0.22.0-rc.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/README.en.md +76 -4
- package/README.md +76 -6
- package/client.js +135 -36
- package/lib/index.d.ts +51 -0
- package/lib/index.js +507 -99
- package/lib/index.js.map +1 -1
- package/lib/probe.d.ts +29 -1
- package/lib/probe.js +98 -19
- package/lib/probe.js.map +1 -1
- package/lib/sftp.js +66 -22
- package/lib/sftp.js.map +1 -1
- package/lib/ssh-config.d.ts +34 -2
- package/lib/ssh-config.js +150 -32
- package/lib/ssh-config.js.map +1 -1
- package/lib/ssh.d.ts +256 -2
- package/lib/ssh.js +637 -6
- package/lib/ssh.js.map +1 -1
- package/lib/tunnels.d.ts +2 -0
- package/lib/tunnels.js +79 -7
- package/lib/tunnels.js.map +1 -1
- package/package.json +7 -5
- package/scripts/integration.mjs +51 -19
- package/scripts/jump-smoke.mjs +175 -0
- package/scripts/lib/proxy-bridge.mjs +30 -0
- package/scripts/preview/harness.js +74 -26
- package/scripts/probe-route-smoke.mjs +10 -1
- package/scripts/proxycommand-smoke.mjs +267 -0
- package/scripts/windows-smoke.mjs +23 -0
package/lib/probe.d.ts
CHANGED
|
@@ -5,11 +5,39 @@ export declare const PROBE_TCP_TIMEOUT_MS = 6000;
|
|
|
5
5
|
export declare const PROBE_AUTH_TIMEOUT_MS = 8000;
|
|
6
6
|
/** 分类结果载荷(HTTP 回传;字段全部可 JSON)。 */
|
|
7
7
|
export interface ProbeResult {
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* tcp 阶段:DNS 解析 + TCP 建连。
|
|
10
|
+
*
|
|
11
|
+
* **有跳板机时探的是跳板机那一跳**(目标根本不能直连),标签与它的结论另见 `jump`——
|
|
12
|
+
* 客户端据此把这一行写成「跳板机 X 通/不通」,而不是让人读成「目标 TCP 可达」。
|
|
13
|
+
* **走代理命令时这一阶段整个跳过**(`skipped=true`):连不连得上由那条命令自己决定,
|
|
14
|
+
* 直连预检探的是目标主机、与本次连接路径无关,报「不可达」纯属误导读者的噪音。
|
|
15
|
+
*/
|
|
9
16
|
tcp: {
|
|
10
17
|
ok: boolean;
|
|
11
18
|
error?: string;
|
|
12
19
|
ms?: number;
|
|
20
|
+
skipped?: boolean;
|
|
21
|
+
};
|
|
22
|
+
/** 跳板机维度(单跳):标签 + 它那一跳的 TCP 预检结论(与 `tcp` 同一份数据,便于客户端直接渲染)。 */
|
|
23
|
+
jump?: {
|
|
24
|
+
label: string;
|
|
25
|
+
tcp: {
|
|
26
|
+
ok: boolean;
|
|
27
|
+
error?: string;
|
|
28
|
+
ms: number;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* 代理命令维度:配了 `proxyCommand` 时非空。
|
|
33
|
+
*
|
|
34
|
+
* `active=false` 表示**配了但闸门关着**(`allowProxyCommand` 未开),本次不会执行任何本机
|
|
35
|
+
* 命令——探针在这里就返回,把开关路径写清楚(而不是让人读成「目标连不上」)。
|
|
36
|
+
* **不回显命令原文**(它可能含凭据)。
|
|
37
|
+
*/
|
|
38
|
+
proxy?: {
|
|
39
|
+
active: boolean;
|
|
40
|
+
error?: string;
|
|
13
41
|
};
|
|
14
42
|
/** hostkey 阶段:TOFU 比对(未到握手时为 unknown)。 */
|
|
15
43
|
hostkey: {
|
package/lib/probe.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { Client } from 'ssh2';
|
|
24
24
|
import { connect as netConnect } from 'node:net';
|
|
25
|
-
import {
|
|
25
|
+
import { attachSshTransport, classifyError, jumpTargetLabel, PROXY_COMMAND_DISABLED, PROXY_COMMAND_NOT_GRANTED, proxyCommandAllowedNow, proxyCommandGrantedNow, proxyFailureSuffix, sanitizeProxyCommand, sshTarget } from './ssh.js';
|
|
26
26
|
/** TCP 预检超时(毫秒):DNS 解析 + 建连。 */
|
|
27
27
|
export const PROBE_TCP_TIMEOUT_MS = 6_000;
|
|
28
28
|
/** ssh2 握手/认证阶段超时(毫秒);覆盖 buildConnectConfig 的 readyTimeout。 */
|
|
@@ -118,16 +118,59 @@ export async function probeSsh(spec, store) {
|
|
|
118
118
|
};
|
|
119
119
|
const port = spec.port ?? 22;
|
|
120
120
|
const target = sshTarget(spec);
|
|
121
|
-
|
|
121
|
+
/*
|
|
122
|
+
* ---- 阶段 0:代理命令闸门 ----
|
|
123
|
+
*
|
|
124
|
+
* 配了 `proxyCommand` 但开关(`allowProxyCommand`)没开时**在这里就返回**:这一档是
|
|
125
|
+
* 「本机任意命令执行」,关着的时候真实连接也会明确失败(见 ssh.ts 的 dialProxyCommand),
|
|
126
|
+
* 所以探针必须报同一件事——否则「试连」会去 TCP 预检目标主机,把用户引到网络排查上。
|
|
127
|
+
*/
|
|
128
|
+
const proxyCommand = sanitizeProxyCommand(spec.proxyCommand);
|
|
129
|
+
const proxyActive = proxyCommand !== undefined && proxyCommandAllowedNow();
|
|
130
|
+
if (proxyCommand !== undefined) {
|
|
131
|
+
// 未启用分两种:**宿主没授权**(要去设环境变量 + 重启)与**开关关着**(去把开关打开)。
|
|
132
|
+
// 合成一句话会让用户对着一个点不动的开关反复点。
|
|
133
|
+
const blocked = proxyCommandGrantedNow() ? PROXY_COMMAND_DISABLED : PROXY_COMMAND_NOT_GRANTED;
|
|
134
|
+
result.proxy = { active: proxyActive, ...(proxyActive ? {} : { error: blocked }) };
|
|
135
|
+
if (!proxyActive) {
|
|
136
|
+
result.tcp = { ok: false, error: blocked, ms: 0 };
|
|
137
|
+
result.auth = { ok: false, error: blocked };
|
|
138
|
+
return finish();
|
|
139
|
+
}
|
|
140
|
+
/*
|
|
141
|
+
* 走代理命令时**不做直连 TCP 预检**:连不连得上由那条命令决定,探目标主机与本次路径无关
|
|
142
|
+
* (典型情况就是目标根本不可直连,报「不可达」纯属误导)。链路结论来自阶段 2 的握手。
|
|
143
|
+
*/
|
|
144
|
+
result.tcp = { ok: false, skipped: true, ms: 0 };
|
|
145
|
+
}
|
|
146
|
+
/*
|
|
147
|
+
* ---- agent 预检(与 spawnSsh 同款,快速失败) ----
|
|
148
|
+
*
|
|
149
|
+
* **位置在代理命令闸门之后**(tty D67,Windows 真机实测纠正过一次顺序):原先它在闸门之前,于是
|
|
150
|
+
* 「配了代理命令 + 宿主没授权 + 这台机器又没有 ssh-agent」三件事同时成立时,探针只报
|
|
151
|
+
* 「agent 认证需要 SSH_AUTH_SOCK」——用户去把 agent 修好、再点一次,才看到真正挡路的那道门。
|
|
152
|
+
* 策略挡路(要不要放行本机命令执行)优先于环境挡路(本机有没有 agent),
|
|
153
|
+
* 也与 HTTP 路由「先过门、再干活」一致。macOS 开发机上因为本机有 agent,看不出来。
|
|
154
|
+
*/
|
|
122
155
|
if (spec.auth === 'agent' && (process.env.SSH_AUTH_SOCK === undefined || process.env.SSH_AUTH_SOCK === '')) {
|
|
123
156
|
const message = 'agent 认证需要 SSH_AUTH_SOCK(本机未运行 ssh-agent 或变量未设置)';
|
|
124
157
|
result.tcp = { ok: false, error: message, ms: 0 };
|
|
125
158
|
result.auth = { ok: false, error: message };
|
|
126
159
|
return finish();
|
|
127
160
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
161
|
+
/*
|
|
162
|
+
* ---- 阶段 1:TCP 预检(DNS + 建连) ----
|
|
163
|
+
*
|
|
164
|
+
* **有跳板机时预检的是跳板机**:目标那一跳根本不能直连,探它只会得到一句「超时」,
|
|
165
|
+
* 而那正是用户要区分的东西。目标那一跳的结论来自阶段 2(经通道握手),见 result.auth。
|
|
166
|
+
* **走代理命令时整段跳过**(上面已经把 tcp 标成 skipped)。
|
|
167
|
+
*/
|
|
168
|
+
const jumpLabel = jumpTargetLabel(spec);
|
|
169
|
+
const tcpHost = spec.jump !== undefined ? spec.jump.host.trim() : spec.host;
|
|
170
|
+
const tcpPort = spec.jump !== undefined ? spec.jump.port ?? 22 : port;
|
|
171
|
+
const tcpPrefix = jumpLabel === '' ? '' : `跳板机 ${jumpLabel} `;
|
|
172
|
+
const tcpResult = !proxyActive && await new Promise((resolve) => {
|
|
173
|
+
const sock = netConnect({ host: tcpHost, port: tcpPort });
|
|
131
174
|
const tcpStart = Date.now();
|
|
132
175
|
const done = (ok, error) => {
|
|
133
176
|
try {
|
|
@@ -139,30 +182,40 @@ export async function probeSsh(spec, store) {
|
|
|
139
182
|
resolve({ ok, error, ms: Date.now() - tcpStart });
|
|
140
183
|
};
|
|
141
184
|
sock.setTimeout(PROBE_TCP_TIMEOUT_MS, () => {
|
|
142
|
-
|
|
185
|
+
// 没配跳板机时仍要点出这条最容易被误读的成因(企业内网主机几乎都要过 bastion)
|
|
186
|
+
const hint = jumpLabel === ''
|
|
187
|
+
? ';若该主机只能经跳板机访问,请在这个连接条目里配置跳板机(也可从 ~/.ssh/config 导入,ProxyJump 会被自动带上)'
|
|
188
|
+
: '';
|
|
189
|
+
done(false, `${tcpPrefix}TCP 连接超时:无响应(检查地址 / 防火墙 / 网络${hint})`);
|
|
143
190
|
});
|
|
144
191
|
sock.once('connect', () => done(true));
|
|
145
192
|
sock.once('error', (error) => {
|
|
146
|
-
done(false, classifyError(error.message));
|
|
193
|
+
done(false, tcpPrefix + classifyError(error.message));
|
|
147
194
|
});
|
|
148
195
|
});
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
196
|
+
if (tcpResult !== false) {
|
|
197
|
+
result.tcp = tcpResult;
|
|
198
|
+
if (jumpLabel !== '')
|
|
199
|
+
result.jump = { label: jumpLabel, tcp: { ...tcpResult, ms: tcpResult.ms } };
|
|
200
|
+
if (!tcpResult.ok) {
|
|
201
|
+
result.auth = { ok: false, error: tcpResult.error };
|
|
202
|
+
return finish();
|
|
203
|
+
}
|
|
153
204
|
}
|
|
154
205
|
// ---- 阶段 2+3:ssh2 握手(host key 交换 + 认证) ----
|
|
206
|
+
// 有跳板机时**两跳都用探针的短超时**:否则「跳板机连不上」会把探针拖到 20s
|
|
155
207
|
let connectConfig;
|
|
208
|
+
let transport;
|
|
156
209
|
try {
|
|
157
|
-
|
|
210
|
+
const attached = await attachSshTransport({ spec, store, readyTimeoutMs: PROBE_AUTH_TIMEOUT_MS });
|
|
211
|
+
connectConfig = attached.connectConfig;
|
|
212
|
+
transport = attached.transport;
|
|
158
213
|
}
|
|
159
214
|
catch (error) {
|
|
160
215
|
const message = error instanceof Error ? error.message : String(error);
|
|
161
216
|
result.auth = { ok: false, error: classifyError(message) };
|
|
162
217
|
return finish();
|
|
163
218
|
}
|
|
164
|
-
// 探针专属更短握手超时(buildConnectConfig 默认 20s 对测试太长)
|
|
165
|
-
connectConfig.readyTimeout = PROBE_AUTH_TIMEOUT_MS;
|
|
166
219
|
const password = spec.auth === 'password' ? connectConfig.password ?? '' : '';
|
|
167
220
|
const tryKeyboard = connectConfig.tryKeyboard === true;
|
|
168
221
|
return new Promise((resolve) => {
|
|
@@ -180,6 +233,14 @@ export async function probeSsh(spec, store) {
|
|
|
180
233
|
catch {
|
|
181
234
|
/* 已断开 */
|
|
182
235
|
}
|
|
236
|
+
try {
|
|
237
|
+
transport.bastion?.end();
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
/* 已断开 */
|
|
241
|
+
}
|
|
242
|
+
// 代理命令是子进程:探针收尾必须杀它(每次试连漏一个常驻进程是很容易漏的地方)
|
|
243
|
+
transport.proxy?.dispose();
|
|
183
244
|
resolve(finish());
|
|
184
245
|
};
|
|
185
246
|
// hostVerifier 的 onResult 同步回调:把结论收集到 hostkeyState
|
|
@@ -199,7 +260,16 @@ export async function probeSsh(spec, store) {
|
|
|
199
260
|
});
|
|
200
261
|
}
|
|
201
262
|
const authStart = Date.now();
|
|
263
|
+
/*
|
|
264
|
+
* **每个回调进来先看 settled**——这不是防御性代码,是修一个真缺陷(2026-09-26 真机验收发现):
|
|
265
|
+
* `settle()` 有幂等守卫,但这些 `result.auth = …` **赋值没有**。而 `resolve(finish())` 交出去的
|
|
266
|
+
* 是**同一个对象**,于是「后到的 close」会把已经定稿的字段覆写掉,调用方看到的是最后那句
|
|
267
|
+
* ——实测症状是 ssh2 连报两条错(`Connection lost before handshake` 带着代理命令的 stderr、
|
|
268
|
+
* 随后 `The operation was aborted` 什么线索都没有),文案被后者盖成一句空话。
|
|
269
|
+
*/
|
|
202
270
|
const timer = setTimeout(() => {
|
|
271
|
+
if (settled)
|
|
272
|
+
return;
|
|
203
273
|
if (seenHostKey) {
|
|
204
274
|
result.hostkey = hostkeyState;
|
|
205
275
|
result.auth = { ok: false, error: '认证/协商超时(服务端在 8s 内未完成认证)', ms: Date.now() - authStart };
|
|
@@ -211,11 +281,15 @@ export async function probeSsh(spec, store) {
|
|
|
211
281
|
}, PROBE_AUTH_TIMEOUT_MS + 1000);
|
|
212
282
|
timer.unref?.();
|
|
213
283
|
conn.on('ready', () => {
|
|
284
|
+
if (settled)
|
|
285
|
+
return;
|
|
214
286
|
result.hostkey = hostkeyState;
|
|
215
287
|
result.auth = { ok: true, ms: Date.now() - authStart };
|
|
216
288
|
settle();
|
|
217
289
|
});
|
|
218
290
|
conn.on('error', (error) => {
|
|
291
|
+
if (settled)
|
|
292
|
+
return;
|
|
219
293
|
const classified = classifyError(error.message);
|
|
220
294
|
if (error.message === 'Host key verification failed' && hostkeyState.state === 'mismatch') {
|
|
221
295
|
result.hostkey = hostkeyState;
|
|
@@ -224,13 +298,16 @@ export async function probeSsh(spec, store) {
|
|
|
224
298
|
return;
|
|
225
299
|
}
|
|
226
300
|
result.hostkey = seenHostKey ? hostkeyState : { state: 'unknown', fingerprint: '' };
|
|
227
|
-
// TCP
|
|
228
|
-
|
|
301
|
+
// TCP / 传输已通:这里只可能是协商 / 认证 / 协议层错误。
|
|
302
|
+
// 代理命令死了的话,ssh2 只会报「握手前连接中断」——把那件事补在后面,别把人支到目标主机上
|
|
303
|
+
result.auth = { ok: false, error: classified + proxyFailureSuffix(transport.proxy), ms: Date.now() - authStart };
|
|
229
304
|
settle();
|
|
230
305
|
});
|
|
231
306
|
conn.on('close', () => {
|
|
232
307
|
// 正常路径(ready / error / 超时)已 settle;未 settle 的 close 兜底
|
|
233
|
-
|
|
308
|
+
if (settled)
|
|
309
|
+
return;
|
|
310
|
+
result.auth = { ok: false, error: `连接已关闭(服务端主动断开)${proxyFailureSuffix(transport.proxy)}`, ms: Date.now() - authStart };
|
|
234
311
|
settle();
|
|
235
312
|
});
|
|
236
313
|
try {
|
|
@@ -238,8 +315,10 @@ export async function probeSsh(spec, store) {
|
|
|
238
315
|
}
|
|
239
316
|
catch (error) {
|
|
240
317
|
const message = error instanceof Error ? error.message : String(error);
|
|
241
|
-
|
|
242
|
-
|
|
318
|
+
if (!settled) {
|
|
319
|
+
result.auth = { ok: false, error: classifyError(message), ms: Date.now() - authStart };
|
|
320
|
+
settle();
|
|
321
|
+
}
|
|
243
322
|
}
|
|
244
323
|
});
|
|
245
324
|
}
|
package/lib/probe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAE7B,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAGvE,gCAAgC;AAChC,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAA;AACzC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAA;AAsB1C,sCAAsC;AACtC,6DAA6D;AAC7D,SAAS,eAAe,CAAC,MAAc,EAAE,IAAY,EAAE,IAAY,EAAE,KAAe,EAAE,OAAe;IACnG,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACrE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;IACnE,OAAO,CACL,gBAAgB,MAAM,QAAQ,KAAK,GAAG,IAAI,eAAe,OAAO,GAAG;QACnE,wEAAwE,CACzE,CAAA;AACH,CAAC;AAED,4DAA4D;AAC5D,SAAS,mBAAmB,CAAC,OAI5B;IACC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;IAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAC9B,IAAI,IAAI,GAAG,EAAE,CAAA;IACb,OAAO,CAAC,IAAY,EAAE,EAAE;QACtB,IAAI,GAAG,IAAI,CAAA;QACX,MAAM,KAAK,GAAG,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QACzC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,kDAAkD;gBAClD,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;gBACnC,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;YACpD,CAAC;iBAAM,CAAC;gBACN,iBAAiB;gBACjB,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;YACnD,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;YACxD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,QAAQ,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA;QACvH,OAAO,KAAK,CAAA;IACd,CAAC,CAAA;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,iBAAiB,CAAC,KAA8B;IAC9D,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACpE,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IAChF,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;IACzC,IAAI,QAAQ,KAAK,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;IAC9C,IAAI,IAAI,GAAG,EAAE,CAAA;IACb,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAChC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,KAAK;YAAE,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAA;QACjG,IAAI,GAAG,KAAK,CAAA;IACd,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAA;IACrF,MAAM,IAAI,GAAY,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IACpD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAC7E,IAAI,OAAO,KAAK,EAAE;YAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAA;QACvD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,MAAM,UAAU,GAAG,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;QAC/E,IAAI,UAAU,KAAK,EAAE;YAAE,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IACrD,CAAC;IACD,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;QACzE,IAAI,QAAQ,KAAK,EAAE;YAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAA;QAC3D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;IACD,IAAI,KAAK,CAAC,YAAY,KAAK,IAAI;QAAE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;IACzD,OAAO,EAAE,IAAI,EAAE,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAa,EAAE,KAAoB;IAChE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAC5B,MAAM,MAAM,GAAgB;QAC1B,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE;QAClB,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE;QAC9C,IAAI,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE;QACnB,OAAO,EAAE,CAAC;KACX,CAAA;IACD,MAAM,MAAM,GAAG,GAAgB,EAAE;QAC/B,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAA;QACvC,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;IAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAE9B,8CAA8C;IAC9C,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,EAAE,CAAC,EAAE,CAAC;QAC3G,MAAM,OAAO,GAAG,kDAAkD,CAAA;QAClE,MAAM,CAAC,GAAG,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,CAAA;QACjD,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;QAC3C,OAAO,MAAM,EAAE,CAAA;IACjB,CAAC;IAED,kCAAkC;IAClC,MAAM,SAAS,GAAG,MAAM,IAAI,OAAO,CAA8C,CAAC,OAAO,EAAE,EAAE;QAC3F,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC3B,MAAM,IAAI,GAAG,CAAC,EAAW,EAAE,KAAc,EAAQ,EAAE;YACjD,IAAI,CAAC;gBACH,IAAI,CAAC,OAAO,EAAE,CAAA;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,OAAO,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAA;QACnD,CAAC,CAAA;QACD,IAAI,CAAC,UAAU,CAAC,oBAAoB,EAAE,GAAG,EAAE;YACzC,IAAI,CAAC,KAAK,EAAE,iCAAiC,CAAC,CAAA;QAChD,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAA4B,EAAE,EAAE;YAClD,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IACF,MAAM,CAAC,GAAG,GAAG,SAAS,CAAA;IACtB,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAA;QACnD,OAAO,MAAM,EAAE,CAAA;IACjB,CAAC;IAED,6CAA6C;IAC7C,IAAI,aAA4B,CAAA;IAChC,IAAI,CAAC;QACH,aAAa,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACtE,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAA;QAC1D,OAAO,MAAM,EAAE,CAAA;IACjB,CAAC;IACD,8CAA8C;IAC9C,aAAa,CAAC,YAAY,GAAG,qBAAqB,CAAA;IAElD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAE,aAAuC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACxG,MAAM,WAAW,GAAI,aAA2C,CAAC,WAAW,KAAK,IAAI,CAAA;IAErF,OAAO,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,EAAE;QAC1C,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,IAAI,WAAW,GAAG,KAAK,CAAA;QACvB,IAAI,YAAY,GAA2B,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,CAAA;QAChF,MAAM,MAAM,GAAG,GAAS,EAAE;YACxB,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,IAAI,CAAC;gBACH,IAAI,CAAC,GAAG,EAAE,CAAA;YACZ,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;QACnB,CAAC,CAAA;QACD,mDAAmD;QACnD,aAAa,CAAC,YAAY,GAAG,mBAAmB,CAAC;YAC/C,IAAI;YACJ,KAAK;YACL,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;gBACjB,WAAW,GAAG,IAAI,CAAA;gBAClB,YAAY,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAA;YAC/C,CAAC;SACF,CAAC,CAAA;QACF,kEAAkE;QAClE,MAAM,IAAI,GAAG,IAAI,MAAM,EAAE,CAAA;QACzB,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC,EAAE,CAAC,sBAAsB,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;gBAClF,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;YACtB,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,CAAC,OAAO,GAAG,YAAY,CAAA;gBAC7B,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;YAC3F,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;YAC1F,CAAC;YACD,MAAM,EAAE,CAAA;QACV,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC,CAAA;QAChC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAA;QAEf,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACpB,MAAM,CAAC,OAAO,GAAG,YAAY,CAAA;YAC7B,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;YACtD,MAAM,EAAE,CAAA;QACV,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YAChC,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YAC/C,IAAI,KAAK,CAAC,OAAO,KAAK,8BAA8B,IAAI,YAAY,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBAC1F,MAAM,CAAC,OAAO,GAAG,YAAY,CAAA;gBAC7B,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;gBACxF,MAAM,EAAE,CAAA;gBACR,OAAM;YACR,CAAC;YACD,MAAM,CAAC,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,CAAA;YACnF,+BAA+B;YAC/B,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;YAC1E,MAAM,EAAE,CAAA;QACV,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACpB,uDAAuD;YACvD,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;YAChF,MAAM,EAAE,CAAA;QACV,CAAC,CAAC,CAAA;QACF,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACtE,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAA;YACtF,MAAM,EAAE,CAAA;QACV,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"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"}
|
package/lib/sftp.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* 下次操作自动重连(不做后台重连循环——SFTP 没有常驻监听需求,与隧道不同;
|
|
7
7
|
* 解析 spec 由调用方每次传入,连接簿凭证热改后天然生效)。
|
|
8
8
|
*
|
|
9
|
-
* 连接建立复用
|
|
9
|
+
* 连接建立复用 prepareSshConnect(含跳板机)——TOFU 与终端会话、
|
|
10
10
|
* 隧道共用同一 HostKeyStore,指纹变更同样拒绝且文案一致;password 认证挂
|
|
11
11
|
* keyboard-interactive 自动应答(同 spawnSsh,很多服务端只开这个)。
|
|
12
12
|
*
|
|
@@ -23,7 +23,7 @@ import { mkdir as fsMkdir, readdir as fsReaddir, rm as fsRm, stat as fsStat } fr
|
|
|
23
23
|
import { basename, dirname, join as pathJoin } from 'node:path';
|
|
24
24
|
import { PassThrough } from 'node:stream';
|
|
25
25
|
import { pipeline } from 'node:stream/promises';
|
|
26
|
-
import {
|
|
26
|
+
import { prepareSshConnect, proxyFailureSuffix, sshTarget } from './ssh.js';
|
|
27
27
|
/** 连接空闲回收阈值:窗口内无任何操作即断开(下次操作自动重连)。 */
|
|
28
28
|
const SFTP_IDLE_MS = 120_000;
|
|
29
29
|
/** 扫描周期。 */
|
|
@@ -53,6 +53,22 @@ export function assertRemovableRemotePath(raw) {
|
|
|
53
53
|
}
|
|
54
54
|
/** OpenSSH 等 server 的 readdir 会带回 '.'/'..':目录列表与递归删除都要跳过。 */
|
|
55
55
|
const DOT_ENTRIES = new Set(['.', '..']);
|
|
56
|
+
/**
|
|
57
|
+
* SFTP 失败文案:`<动作> <对象>: <原因>`。
|
|
58
|
+
*
|
|
59
|
+
* 为什么必须带对象(D59):agent 常把 sftp_list 当「这个路径存不存在」的探测用,
|
|
60
|
+
* 批量调用时只看到「读取目录失败: No such file」根本判断不出是哪一条失败——只能靠
|
|
61
|
+
* 事件序号回推。path / from→to 就在各调用点作用域里,没有理由不带。
|
|
62
|
+
*
|
|
63
|
+
* ssh2 把 SFTP 状态码挂在 `err.code` 上(SFTP.js `err.code = errorCode`):
|
|
64
|
+
* NO_SUCH_FILE / PERMISSION_DENIED 单独点明,省得调用方从英文 errno 里猜语义。
|
|
65
|
+
*/
|
|
66
|
+
function sftpFail(action, target, error, note = '') {
|
|
67
|
+
const code = typeof error === 'object' && error !== null ? error.code : undefined;
|
|
68
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
69
|
+
const detail = code === 2 ? '不存在(NO_SUCH_FILE)' : code === 3 ? '权限不足(PERMISSION_DENIED)' : reason;
|
|
70
|
+
return new Error(`${action} ${target}: ${detail}${note}`);
|
|
71
|
+
}
|
|
56
72
|
/** 远程路径拼接(POSIX 语义;本机路径拼接用 node:path)。 */
|
|
57
73
|
function joinRemotePath(base, name) {
|
|
58
74
|
return (base.endsWith('/') ? base : base + '/') + name;
|
|
@@ -198,7 +214,7 @@ export class SftpManager {
|
|
|
198
214
|
catch (error) {
|
|
199
215
|
// 请求的根目录读不到(不存在/权限)→ 明确报错;子目录失败记入 errors 继续
|
|
200
216
|
if (isRoot)
|
|
201
|
-
throw
|
|
217
|
+
throw sftpFail('读取目录失败', dir, error);
|
|
202
218
|
errors.push({ path: dir, message: error instanceof Error ? error.message : String(error) });
|
|
203
219
|
return;
|
|
204
220
|
}
|
|
@@ -238,7 +254,7 @@ export class SftpManager {
|
|
|
238
254
|
async rename(spec, from, to) {
|
|
239
255
|
const sftp = await this.acquire(spec);
|
|
240
256
|
await new Promise((resolve, reject) => {
|
|
241
|
-
sftp.rename(from.trim(), to.trim(), (error) => (error != null ? reject(
|
|
257
|
+
sftp.rename(from.trim(), to.trim(), (error) => (error != null ? reject(sftpFail('重命名失败', `${from.trim()} → ${to.trim()}`, error)) : resolve()));
|
|
242
258
|
});
|
|
243
259
|
}
|
|
244
260
|
/**
|
|
@@ -285,7 +301,7 @@ export class SftpManager {
|
|
|
285
301
|
const target = path.trim();
|
|
286
302
|
if (append) {
|
|
287
303
|
const stream = sftp.createWriteStream(target, { flags: 'a' });
|
|
288
|
-
const done = this.streamDone(stream, () => { });
|
|
304
|
+
const done = this.streamDone(stream, () => { }, target);
|
|
289
305
|
done.catch(() => { });
|
|
290
306
|
return { stream, done, writePath: target };
|
|
291
307
|
}
|
|
@@ -308,7 +324,7 @@ export class SftpManager {
|
|
|
308
324
|
stream.on('error', (error) => {
|
|
309
325
|
settled = true;
|
|
310
326
|
dropPart();
|
|
311
|
-
reject(
|
|
327
|
+
reject(sftpFail('上传写入失败', target, error));
|
|
312
328
|
});
|
|
313
329
|
stream.on('close', () => {
|
|
314
330
|
if (settled)
|
|
@@ -364,10 +380,10 @@ export class SftpManager {
|
|
|
364
380
|
}
|
|
365
381
|
}
|
|
366
382
|
/** WriteStream 的 done Promise(close 即 resolve,error reject);onClose 钩子供覆盖写路径塞落盘逻辑。 */
|
|
367
|
-
streamDone(stream, onClose) {
|
|
383
|
+
streamDone(stream, onClose, target) {
|
|
368
384
|
return new Promise((resolve, reject) => {
|
|
369
385
|
stream.on('error', (error) => {
|
|
370
|
-
reject(
|
|
386
|
+
reject(sftpFail('上传写入失败', target, error));
|
|
371
387
|
});
|
|
372
388
|
stream.on('close', () => {
|
|
373
389
|
onClose();
|
|
@@ -688,12 +704,19 @@ export class SftpManager {
|
|
|
688
704
|
existing.lastUsed = Date.now();
|
|
689
705
|
return existing.sftp;
|
|
690
706
|
}
|
|
691
|
-
const target = sshTarget(spec);
|
|
692
707
|
const conn = new Client();
|
|
693
708
|
let sftp;
|
|
709
|
+
let bastion = null;
|
|
710
|
+
let proxy = null;
|
|
711
|
+
let target = sshTarget(spec);
|
|
694
712
|
try {
|
|
695
|
-
|
|
696
|
-
const
|
|
713
|
+
// 与终端/隧道/探针共用同一条准备路径:跳板机 / 代理命令只在 prepareSshConnect 里拨一次
|
|
714
|
+
const prepared = await prepareSshConnect({ spec, store: this.store, logger: this.logger });
|
|
715
|
+
const connectConfig = prepared.connectConfig;
|
|
716
|
+
const policy = prepared.policy;
|
|
717
|
+
bastion = prepared.bastion;
|
|
718
|
+
proxy = prepared.proxy;
|
|
719
|
+
target = prepared.target;
|
|
697
720
|
// password 认证挂 keyboard-interactive 自动应答(同 spawnSsh;
|
|
698
721
|
// tryKeyboard 只在 password 分支置位,见 buildConnectConfig)
|
|
699
722
|
if (connectConfig.tryKeyboard === true) {
|
|
@@ -712,17 +735,21 @@ export class SftpManager {
|
|
|
712
735
|
if (!settled) {
|
|
713
736
|
settled = true;
|
|
714
737
|
const mismatch = policy.mismatchMessage();
|
|
715
|
-
reject(new Error(mismatch ?? `SSH 连接失败(${target}): ${error.message}`));
|
|
738
|
+
reject(new Error(mismatch ?? `SSH 连接失败(${target}): ${error.message}${proxyFailureSuffix(proxy)}`));
|
|
716
739
|
}
|
|
717
740
|
else {
|
|
718
741
|
this.logger.warn(`[dsh-tty] sftp ${target} 连接错误: ${error.message}`);
|
|
719
742
|
}
|
|
720
743
|
});
|
|
721
744
|
conn.on('close', () => {
|
|
722
|
-
//
|
|
745
|
+
// 连接断开:丢弃池内条目,下次操作自动重连。
|
|
746
|
+
// **必须走 close(rt) 而不是只 delete**(**D65**):跳板机 / 代理命令是「另一条连接 / 另一个进程」,
|
|
747
|
+
// 只摘池条目会把它们留在原地(前者靠 keepalive 一直挂着、后者变常驻孤儿)。
|
|
723
748
|
const rt = this.conns.get(signature);
|
|
724
|
-
if (rt !== undefined && rt.conn === conn)
|
|
749
|
+
if (rt !== undefined && rt.conn === conn) {
|
|
725
750
|
this.conns.delete(signature);
|
|
751
|
+
this.close(rt);
|
|
752
|
+
}
|
|
726
753
|
});
|
|
727
754
|
try {
|
|
728
755
|
conn.connect(connectConfig);
|
|
@@ -747,10 +774,18 @@ export class SftpManager {
|
|
|
747
774
|
catch {
|
|
748
775
|
/* 未建立 */
|
|
749
776
|
}
|
|
777
|
+
try {
|
|
778
|
+
bastion?.end();
|
|
779
|
+
}
|
|
780
|
+
catch {
|
|
781
|
+
/* 未建立 */
|
|
782
|
+
}
|
|
783
|
+
proxy?.dispose();
|
|
784
|
+
proxy = null;
|
|
750
785
|
throw error;
|
|
751
786
|
}
|
|
752
787
|
this.logger.info(`[dsh-tty] sftp ${target} 就绪`);
|
|
753
|
-
const rt = { spec, signature, conn, sftp, lastUsed: Date.now() };
|
|
788
|
+
const rt = { spec, signature, conn, bastion, proxy, sftp, lastUsed: Date.now() };
|
|
754
789
|
this.conns.set(signature, rt);
|
|
755
790
|
return sftp;
|
|
756
791
|
}
|
|
@@ -776,13 +811,22 @@ export class SftpManager {
|
|
|
776
811
|
catch {
|
|
777
812
|
/* 已断开 */
|
|
778
813
|
}
|
|
814
|
+
try {
|
|
815
|
+
rt.bastion?.end();
|
|
816
|
+
}
|
|
817
|
+
catch {
|
|
818
|
+
/* 已断开 */
|
|
819
|
+
}
|
|
820
|
+
rt.bastion = null;
|
|
821
|
+
rt.proxy?.dispose();
|
|
822
|
+
rt.proxy = null;
|
|
779
823
|
}
|
|
780
824
|
/* -------------------------------------------------------------- */
|
|
781
825
|
/* SFTPWrapper 回调的 Promise 化与递归删除 */
|
|
782
826
|
/* -------------------------------------------------------------- */
|
|
783
827
|
realpath(sftp, path) {
|
|
784
828
|
return new Promise((resolve, reject) => {
|
|
785
|
-
sftp.realpath(path, (error, absPath) => (error !== undefined ? reject(
|
|
829
|
+
sftp.realpath(path, (error, absPath) => (error !== undefined ? reject(sftpFail('realpath 失败', path, error)) : resolve(absPath)));
|
|
786
830
|
});
|
|
787
831
|
}
|
|
788
832
|
/** stat 的静默版:路径不存在等错误一律回 null(mkdir -p 的逐级探测用)。 */
|
|
@@ -793,21 +837,21 @@ export class SftpManager {
|
|
|
793
837
|
}
|
|
794
838
|
mkdirOne(sftp, path) {
|
|
795
839
|
return new Promise((resolve, reject) => {
|
|
796
|
-
sftp.mkdir(path, (error) => (error != null ? reject(
|
|
840
|
+
sftp.mkdir(path, (error) => (error != null ? reject(sftpFail('创建目录失败', path, error)) : resolve()));
|
|
797
841
|
});
|
|
798
842
|
}
|
|
799
843
|
readdir(sftp, path) {
|
|
800
844
|
return new Promise((resolve, reject) => {
|
|
801
|
-
sftp.readdir(path, (error, list) => (error !== undefined ? reject(
|
|
845
|
+
sftp.readdir(path, (error, list) => (error !== undefined ? reject(sftpFail('读取目录失败', path, error)) : resolve(list)));
|
|
802
846
|
});
|
|
803
847
|
}
|
|
804
848
|
async removeEntry(sftp, path, recursive) {
|
|
805
849
|
const stats = await new Promise((resolve, reject) => {
|
|
806
|
-
sftp.lstat(path, (error, stats) => (error !== undefined ? reject(
|
|
850
|
+
sftp.lstat(path, (error, stats) => (error !== undefined ? reject(sftpFail('删除失败', path, error)) : resolve(stats)));
|
|
807
851
|
});
|
|
808
852
|
if (!stats.isDirectory()) {
|
|
809
853
|
await new Promise((resolve, reject) => {
|
|
810
|
-
sftp.unlink(path, (error) => (error != null ? reject(
|
|
854
|
+
sftp.unlink(path, (error) => (error != null ? reject(sftpFail('删除失败', path, error)) : resolve()));
|
|
811
855
|
});
|
|
812
856
|
return;
|
|
813
857
|
}
|
|
@@ -815,7 +859,7 @@ export class SftpManager {
|
|
|
815
859
|
await new Promise((resolve, reject) => {
|
|
816
860
|
// 不预设原因:非空与权限拒绝在 SFTP 层都是笼统的 Failure,把两种可能
|
|
817
861
|
// 一并列出让用户自行分辨(此前一律归因为「非空」误导权限问题)
|
|
818
|
-
sftp.rmdir(path, (error) => (error != null ? reject(
|
|
862
|
+
sftp.rmdir(path, (error) => (error != null ? reject(sftpFail('删除目录失败', path, error, '(目录非空时需 recursive:true;若非此原因,多为账号对该目录无写权限)')) : resolve()));
|
|
819
863
|
});
|
|
820
864
|
return;
|
|
821
865
|
}
|
|
@@ -827,7 +871,7 @@ export class SftpManager {
|
|
|
827
871
|
await this.removeEntry(sftp, base + child.filename, true);
|
|
828
872
|
}
|
|
829
873
|
await new Promise((resolve, reject) => {
|
|
830
|
-
sftp.rmdir(path, (error) => (error != null ? reject(
|
|
874
|
+
sftp.rmdir(path, (error) => (error != null ? reject(sftpFail('删除目录失败', path, error)) : resolve()));
|
|
831
875
|
});
|
|
832
876
|
}
|
|
833
877
|
}
|