dsh-ssh-workbench 0.0.0-stage → 1.6.4
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/CHANGELOG.md +504 -0
- package/CONTRIBUTING.md +62 -0
- package/LICENSE +21 -0
- package/README.md +159 -2
- package/SECURITY.md +25 -0
- package/cordis.patch.yml +5 -0
- package/docs/architecture.md +124 -0
- package/docs/quickstart.md +94 -0
- package/lib/client.js +4977 -0
- package/lib/core/activity.js +83 -0
- package/lib/core/background.js +69 -0
- package/lib/core/broker.js +799 -0
- package/lib/core/dialect.js +28 -0
- package/lib/core/errors.js +138 -0
- package/lib/core/gate-pwsh.js +88 -0
- package/lib/core/gate.js +572 -0
- package/lib/core/guard.js +71 -0
- package/lib/core/known-hosts.js +74 -0
- package/lib/core/local-file-api.js +174 -0
- package/lib/core/localfs.js +381 -0
- package/lib/core/paths.js +104 -0
- package/lib/core/posix-quote.js +4 -0
- package/lib/core/prefs.js +38 -0
- package/lib/core/remote-bash-tool.js +321 -0
- package/lib/core/remote-bash.js +337 -0
- package/lib/core/secrets.js +96 -0
- package/lib/core/server-reference.js +299 -0
- package/lib/core/shell-adapters.js +48 -0
- package/lib/core/ssh.js +761 -0
- package/lib/core/store.js +83 -0
- package/lib/core/targets.js +250 -0
- package/lib/core/terminals.js +299 -0
- package/lib/core/win32-adapter.js +141 -0
- package/lib/index.js +450 -0
- package/lib/routes.js +733 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +88 -4
- package/vendor/NOTICE.md +50 -0
- package/vendor/XTERM-LICENSE +21 -0
- package/vendor/node_modules/asn1/LICENSE +19 -0
- package/vendor/node_modules/asn1/README.md +50 -0
- package/vendor/node_modules/asn1/lib/ber/errors.js +13 -0
- package/vendor/node_modules/asn1/lib/ber/index.js +27 -0
- package/vendor/node_modules/asn1/lib/ber/reader.js +262 -0
- package/vendor/node_modules/asn1/lib/ber/types.js +36 -0
- package/vendor/node_modules/asn1/lib/ber/writer.js +317 -0
- package/vendor/node_modules/asn1/lib/index.js +20 -0
- package/vendor/node_modules/asn1/package.json +31 -0
- package/vendor/node_modules/bcrypt-pbkdf/CONTRIBUTING.md +13 -0
- package/vendor/node_modules/bcrypt-pbkdf/LICENSE +66 -0
- package/vendor/node_modules/bcrypt-pbkdf/README.md +45 -0
- package/vendor/node_modules/bcrypt-pbkdf/index.js +556 -0
- package/vendor/node_modules/bcrypt-pbkdf/package.json +15 -0
- package/vendor/node_modules/safer-buffer/LICENSE +21 -0
- package/vendor/node_modules/safer-buffer/Readme.md +156 -0
- package/vendor/node_modules/safer-buffer/dangerous.js +58 -0
- package/vendor/node_modules/safer-buffer/package.json +34 -0
- package/vendor/node_modules/safer-buffer/safer.js +77 -0
- package/vendor/node_modules/tweetnacl/AUTHORS.md +28 -0
- package/vendor/node_modules/tweetnacl/LICENSE +24 -0
- package/vendor/node_modules/tweetnacl/README.md +459 -0
- package/vendor/node_modules/tweetnacl/nacl-fast.js +2388 -0
- package/vendor/node_modules/tweetnacl/nacl.js +1175 -0
- package/vendor/node_modules/tweetnacl/package.json +58 -0
- package/vendor/ssh2/LICENSE +19 -0
- package/vendor/ssh2/lib/Channel.js +295 -0
- package/vendor/ssh2/lib/agent.js +1123 -0
- package/vendor/ssh2/lib/client.js +2176 -0
- package/vendor/ssh2/lib/http-agents.js +84 -0
- package/vendor/ssh2/lib/index.js +44 -0
- package/vendor/ssh2/lib/keygen.js +582 -0
- package/vendor/ssh2/lib/protocol/Protocol.js +2136 -0
- package/vendor/ssh2/lib/protocol/SFTP.js +4052 -0
- package/vendor/ssh2/lib/protocol/constants.js +356 -0
- package/vendor/ssh2/lib/protocol/crypto/poly1305.js +43 -0
- package/vendor/ssh2/lib/protocol/crypto.js +1602 -0
- package/vendor/ssh2/lib/protocol/handlers.js +16 -0
- package/vendor/ssh2/lib/protocol/handlers.misc.js +1285 -0
- package/vendor/ssh2/lib/protocol/kex.js +1908 -0
- package/vendor/ssh2/lib/protocol/keyParser.js +1484 -0
- package/vendor/ssh2/lib/protocol/node-fs-compat.js +115 -0
- package/vendor/ssh2/lib/protocol/utils.js +356 -0
- package/vendor/ssh2/lib/protocol/zlib.js +255 -0
- package/vendor/ssh2/lib/server.js +1380 -0
- package/vendor/ssh2/lib/utils.js +336 -0
- package/vendor/ssh2/package.json +34 -0
- package/vendor/xterm.js +53 -0
package/README.md
CHANGED
|
@@ -1,3 +1,160 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SSH Workbench(dsh-ssh-workbench)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
DeepSeek Harness 的**远程工作台**:SSH 终端、本地与远程文件、@服务器 对话执行,Windows 宿主和目标都能用。
|
|
4
|
+
|
|
5
|
+
不是又一个 SSH 客户端:它把远程执行接进 DSH 的对话与审批,把终端、SFTP 文件管理和本地文件放在同一个工作台里;安装包自包含、开箱即用。
|
|
6
|
+
|
|
7
|
+
插件不改 DSH 的本地工具语义;左侧导航提供一个独立的「远程工作台」,把终端与文件管理放在一起(本地和远程都能用)。对话里 `@资源名` 之后,命令在目标上执行:POSIX 宿主复用原生 `bash`(结果仍是原生终端卡片);Windows 宿主没有内置 `bash`,改用插件自有的 `remote_bash`。Windows 目标(PowerShell)在两种宿主上都经 `remote_pwsh` 执行。原生 `bash` / `pwsh` 始终只在本机生效。没有 `@` 时一切行为不变。模型侧新增的工具是 `ssh_workbench_target`(切换目标)和按需出现的 `remote_bash` / `remote_pwsh`。另外保留一道**危险命令黑名单**作为兜底。
|
|
8
|
+
|
|
9
|
+
- 适用:DSH 0.2.1-rc.1 ~ 0.2.x(`engines.dsh: >=0.2.1-rc.1 <0.3.0`)
|
|
10
|
+
- 平台:macOS / Linux / Windows 上的 DSH;远程目标支持 POSIX 与 Windows(PowerShell)
|
|
11
|
+
|
|
12
|
+
## 能力
|
|
13
|
+
|
|
14
|
+
| 能力 | 说明 |
|
|
15
|
+
|---|---|
|
|
16
|
+
| 远程资源纳管 | 右侧栏/设置页:增删改查、连接测试、host key 指纹确认、密码/私钥凭据(0600 存储);连接测试/选中目标后会采集 hostname 等信息(hostname 仅用于目标上下文;内核/磁盘只存储,不在列表展示) |
|
|
17
|
+
| `@资源` 绑定 | 消息里 `@web-1` 后,命令在 web-1 上执行(资源名支持中文/非 ASCII);`@` 多个资源时需用 `ssh_workbench_target` 选择,未选择前远程工作台会报 `TARGET_NOT_SELECTED` 而不是静默走本地 |
|
|
18
|
+
| Windows 宿主 | Windows 上的 DSH 没有原生 `bash`(DSH 按平台禁用):插件注册 `remote_bash` 用于 POSIX 目标,参数与行为对齐原生 bash 路由;原生 `pwsh` 仍只作用于本机 |
|
|
19
|
+
| Windows 目标 | Windows 目标经插件自有的 `remote_pwsh` 执行:命令包成 UTF-16LE 的 `-EncodedCommand` 脚本(避免引号转义),强制 UTF-8 输出并回传真实退出码;PowerShell 危险命令另有黑名单 |
|
|
20
|
+
| 方言探测 | 目标实际是 POSIX 还是 Windows 由连接后的 `uname -s` / `cmd /c ver` 探测并写入 `facts.dialect`,不依赖手工填写的 `platform`;探测结果用于选择 `remote_bash` / `remote_pwsh`、超时包装和目标上下文文案 |
|
|
21
|
+
| `remote_bash` / `remote_pwsh` | `command`、`workdir`(绝对路径 / `~/x` / 相对路径)、`timeoutMs`、取消沿用同一套语义;POSIX 目标超时后远端命令组会被终止(远端有 `timeout` 时含 `-k` 补 KILL),Windows 目标只能客户端停止等待 |
|
|
22
|
+
| 结果输出 | POSIX 宿主上的 POSIX 目标仍是 DSH 原生 bash 终端卡片;`remote_bash` / `remote_pwsh` 返回带 target / cwd / 退出码 / stdout / stderr 的文本结果 |
|
|
23
|
+
| 后台任务 | `run_in_background: true` 在远端起**脱离会话**的进程:POSIX 用 `nohup` 重定向到 `/tmp` 日志,Windows 用 `Start-Process` + 日志文件;结果返回 pid、日志路径和读取/停止命令(`tail -f` / `kill`、`Get-Content -Wait` / `Stop-Process`)。它不注册到 DSH 本地 `job_*` 注册表,进程在工具调用返回后继续运行 |
|
|
24
|
+
| 平台徽标 | 资源列表/设置页显示 **Linux / Windows** 徽标(来自连接后探测的 `facts.dialect`,不是手填字段);连接测试结果也显示探测到的平台 |
|
|
25
|
+
| 目标切换 | `ssh_workbench_target({ server: "web-1" })`;`server: "local"` 回到本机;切换后首条命令的 stderr、bash 卡片 cwd 前缀和 composer 下方参数行都会标出当前目标 |
|
|
26
|
+
| 远程工作台 | 左侧导航的独立页面:左侧终端(本地终端 / 远程 SSH 终端),右侧文件管理(本地用户主目录 / 远程 SFTP,远程默认打开登录 home),文件可**在工作台内直接预览**,拖动分隔条调整宽度;每个页签一个终端会话,仅活动页签轮询、非活动页签暂停并在切回时续读(UI 能力,不占模型工具) |
|
|
27
|
+
| 侧边栏开关 | 插件管理 → 远程工作台 → 页面里的「在侧边栏显示远程工作台」可关闭左侧导航入口;关闭后 `@资源名` 远程执行、设置页与模型工具不受影响 |
|
|
28
|
+
| 危险命令黑名单 | `rm -rf /`、`mkfs`、`dd of=/dev/*`、`fdisk/parted/wipefs`、改根目录权限、fork bomb 等同步拦截;多行脚本、`&`、引号/转义、路径变体、`$()`/`eval` 都会先还原再判断;其他命令交给 DSH 审批 |
|
|
29
|
+
|
|
30
|
+
**不做**:诊断包、HTTP 探测、批量执行、远程 `read/write/edit/glob/grep`(这些工具始终只作用于 DSH 主机;远程文件操作用对应的远程 shell 工具,如 `cat`、`tee`、`sed`、`Get-Content`)。也**不做**命令分级(allow/guarded)、AI 风险解释和审计。
|
|
31
|
+
|
|
32
|
+
## 安装
|
|
33
|
+
|
|
34
|
+
DSH 插件管理里搜索 `dsh-ssh-workbench` 安装,或:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
dsh plugin --profile desktop add dsh-ssh-workbench
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
从源码构建:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm test
|
|
44
|
+
npm run pack
|
|
45
|
+
# 然后在 DSH 的插件管理里安装 dist/dsh-ssh-workbench-1.6.4.tgz
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
发布包是**自包含**的:SSH 传输依赖(纯 JS 的 ssh2 及其依赖)已放在 `vendor/` 里随包携带,安装时不会运行 `node-gyp`、不需要 Xcode Command Line Tools,也不会额外下载依赖;包体积因此略大(约 0.5 MB),换来任何机器开箱即装。组件与许可证见 `vendor/NOTICE.md`。
|
|
49
|
+
|
|
50
|
+
本地开发时,也可以在 DSH 的插件管理页直接安装本目录(Bundle 安装会读取 `package.json` 的 `dsh` 字段)。
|
|
51
|
+
|
|
52
|
+
安装后在 **设置 → 远程工作台** 里添加资源。
|
|
53
|
+
|
|
54
|
+
## 用法
|
|
55
|
+
|
|
56
|
+
1. 先说目标,再说要做什么:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
@web-1 看下磁盘和内存
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
模型会调用 `bash`(Windows 宿主上是 `remote_bash`;Windows 目标是 `remote_pwsh`),命令实际跑在目标上。`read` / `write` / `edit` / `glob` / `grep` 仍然作用于本机;要操作远程文件,直接用远程 shell 工具:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
@web-1 把 /etc/nginx/nginx.conf 里 worker_connections 改成 2048,改完 nginx -t
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
2. 同时提到多个资源时,模型需要先选择目标:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
@web-1 @db-1 各自看下磁盘
|
|
72
|
+
→ 模型调用 ssh_workbench_target({ server: "web-1" }) → bash df -h
|
|
73
|
+
→ 模型调用 ssh_workbench_target({ server: "db-1" }) → bash df -h
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
3. 切回本机:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
ssh_workbench_target({ server: "local" })
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 安全模型
|
|
83
|
+
|
|
84
|
+
- **黑名单兜底**:远程 `bash` / `remote_bash` / `remote_pwsh` 执行前经过同步、单调的 `ctx.tools.guard()`,命中机器毁灭类命令直接拒绝;该拦截不受审批策略影响。POSIX 规则先按 shell 语义还原(去引号/转义、剥包装、路径规范化、`$()`/`eval` 递归)再匹配,PowerShell 规则覆盖 `Format-Volume`、`Clear-Disk`、`diskpart`、`bcdedit`、整盘递归删除等;两者都只是 best-effort。
|
|
85
|
+
- **审批**:插件不做自己的 ask 清单,远程命令是否弹审批完全由 DSH 的会话预设(`ask` / `never`)决定。
|
|
86
|
+
- **凭据**:密码存于 `~/.dsh/ssh-workbench/`(0600 文件 + 本机密钥),私钥只存路径;servers.json 0600。
|
|
87
|
+
- **主机身份**:严格校验 known_hosts;未知指纹会显示 SHA256 并询问是否信任,由用户决定;信任后写入插件自己的 known_hosts。**如果服务器重装或更换导致指纹变化,连接会被拒绝并提示「服务器主机密钥已变化」**,核对后可在界面点「更新信任」。
|
|
88
|
+
- **本地文件面板**:本地文件浏览/读写/删除默认在本地用户主目录内进行(可用 `localRoot` 改到其他绝对路径);指向目录外的符号链接与越界路径一律拒绝,删除链接只删除链接本身。
|
|
89
|
+
- **注意**:远程命令在服务器上执行,不受 DSH 本地文件沙箱约束;安全边界是服务器自身的权限、主机身份校验和黑名单。
|
|
90
|
+
|
|
91
|
+
## 已知限制
|
|
92
|
+
|
|
93
|
+
- **stdout/stderr 顺序**:两者是独立管道,收集后分开返回(与原生 bash 的值契约一致),交错顺序会丢失;看 `make`/`pip install` 这类日志时需要留意。
|
|
94
|
+
- **Windows 本地路径**:工作台本地文件面板已按 Windows 分隔符处理面包屑与文件名;极少数外部工具生成的混合分隔符路径仍可能显示成一段,可在路径编辑框直接输入绝对路径。
|
|
95
|
+
- **后台任务**:`run_in_background` 返回的是远端 pid + 日志,不是 DSH 本地 job id;`timeoutMs` 和取消只影响启动调用,不作用于已脱离的进程。POSIX 的 `/tmp` 日志可能被系统清理(按 tmp 策略),重要输出请自行重定向到持久目录。
|
|
96
|
+
- **超时终止**:远端有 `timeout` 时,超时会连同远端进程组一起终止(支持 `-k` 时再补一次 KILL,缓冲时间可用 `timeoutKillAfterMs` 调整);远端没有 `timeout` 时只能停止等待,stderr 会提示"命令可能仍在运行"。**取消(Esc)不会立刻杀远端**:通道关闭后远端仍会计时到自己的 deadline。
|
|
97
|
+
- **stdin 恒为 EOF**:远程命令的 stdin 在启动后立即关闭(等价 `</dev/null`),`cat`/`read` 等读 stdin 的命令会直接得到 EOF。
|
|
98
|
+
- **文件工具仍在本地**:`read`/`write`/`edit`/`glob`/`grep` 不受目标影响;远程文件请走对应的远程 shell 工具或右侧栏 SFTP 面板。`working_directory` 只影响本地工具,远程目录用远程 shell 工具的 `workdir` 参数。
|
|
99
|
+
- **并发由 DSH 调度**:插件为单台服务器提供最多 6 条并发通道,但同一轮里多个 `bash` 调用是否并行由 DSH 的工具调度决定。
|
|
100
|
+
- **目标标识**:DSH 的 bash 卡片是官方渲染且没有装饰插槽,插件不替换卡片;当前用“切换后首条命令 stderr 行 + cwd 前缀(`web-1:/var/log`)+ composer 下方参数行目标指示”标出目标。
|
|
101
|
+
- **侧边栏开关**:开关存放在 `~/.dsh/ssh-workbench/prefs.json`,在插件管理里保存后当前窗口立即生效;关闭时左侧导航不再出现远程工作台入口,右侧栏的「远程工作台」「远程文件」页签保持不变。
|
|
102
|
+
- **终端生命周期**:终端会话跟随工作台页面/页签,关闭页签或离开工作台会结束会话;页面刷新/关闭时通过 `sendBeacon` 尽力补发关闭,但进程崩溃或 Host 异常退出后仍依赖 30 分钟空闲回收(尚未做跨页面保活或重连恢复)。本地终端依赖 Host 的 PTY 服务,不可用时给出提示。
|
|
103
|
+
- **本地文件边界**:工作台的本地文件面板与本地终端默认以**本地用户主目录**为根(`$HOME`,与常规 SSH 客户端的「本地」面板一致,面包屑显示真实路径),越界路径与指向外部的符号链接都会被拒绝;需要固定其他目录时用 `localRoot` 配置(绝对路径或 `~/...`),需要操作主目录以外的本地路径时用本地终端。远程文件仍走 SFTP,远程文件面板默认打开登录 home。
|
|
104
|
+
- **终端渲染资源**:xterm 随客户端 bundle 内置(`vendor/xterm.js` 只是构建输入,不再有运行时脚本路由),不依赖额外脚本路由或 CSP 放行;首次打开工作台时加载。
|
|
105
|
+
- **终端操作边界**:本地/远程终端是用户主动输入,不经过 agent 的审批与黑名单;SSH 权限边界不变。
|
|
106
|
+
- **黑名单是 best-effort**:`bash -c`、base64、脚本文件、解释器 heredoc 正文不会被解析;heredoc 正文会按可执行文本检查(fail-closed,写脚本时可能误拦)。真正的边界是 SSH 最小权限 + host-key + DSH 审批。
|
|
107
|
+
|
|
108
|
+
## 配置
|
|
109
|
+
|
|
110
|
+
在 profile 的 `cordis.patch.yml` 里覆盖(只写想改的字段):
|
|
111
|
+
|
|
112
|
+
| 键 | 默认 | 说明 |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| `commandTimeoutMs` | `120000` | 单条远程命令默认超时;模型可用 bash 的 `timeoutMs` 覆盖 |
|
|
115
|
+
| `maxCommandTimeoutMs` | `1800000` | 单条远程命令超时上限 |
|
|
116
|
+
| `timeoutKillAfterMs` | `5000` | 远端 `timeout -k` 的宽限:TERM 后多久补 SIGKILL;0 = 只用 TERM |
|
|
117
|
+
| `maxOutputBytes` | `102400` | stdout 保留上限(头尾保留,中间截断) |
|
|
118
|
+
| `maxStderrBytes` | `16384` | stderr 独立保留上限(默认明显小于 stdout,保护上下文) |
|
|
119
|
+
| `transferChunkTimeoutMs` | `30000` | SFTP 分块读写看门狗;卡死时关闭会话,UI 可从 offset 续传 |
|
|
120
|
+
| `connectTimeoutMs` | `15000` | SSH 建连超时 |
|
|
121
|
+
| `hostKeyMode` | `strict` | `strict` / `accept-new` |
|
|
122
|
+
| `connectionPool` | `true` | 每台服务器复用一条连接 |
|
|
123
|
+
| `poolIdleMs` | `90000` | 空闲连接回收时间 |
|
|
124
|
+
| `poolMaxServers` | `8` | 连接池最多缓存的目标数 |
|
|
125
|
+
| `maxChannelsPerServer` | `6` | 单连接并发通道上限 |
|
|
126
|
+
| `prewarm` | `true` | UI 选中服务器时预热连接 |
|
|
127
|
+
| `targetContext` | `true` | 自动绑定 `@资源名` 并注入目标上下文;关掉后不自动绑定(仍可手动用 `ssh_workbench_target`) |
|
|
128
|
+
| `localRoot` | `""`(空 = 用户主目录) | 工作台本地文件面板与本地终端的根目录;必须是绝对路径或 `~/...`,非法值回退用户主目录 |
|
|
129
|
+
|
|
130
|
+
> 右侧栏的工作台开关不在 `cordis.patch.yml` 里,而是在 **插件管理 → 远程工作台** 页面里的「在侧边栏显示远程工作台」;它只影响 UI 入口,不影响模型工具。
|
|
131
|
+
|
|
132
|
+
示例:
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
- id: dsh-ssh-workbench
|
|
136
|
+
name: 'dsh-ssh-workbench'
|
|
137
|
+
config:
|
|
138
|
+
commandTimeoutMs: 300000
|
|
139
|
+
maxOutputBytes: 262144
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## 开发
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npm test # 单元测试(无需网络或真实 SSH)
|
|
146
|
+
npm run test:ssh # SSH 传输集成(进程内 ssh2.Server)
|
|
147
|
+
npm run test:ssh:sftp # SFTP 集成(进程内 ssh2.Server)
|
|
148
|
+
npm run pack # 打包到 dist/
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
更多文档:[快速上手](docs/quickstart.md) · [架构说明](docs/architecture.md) · [贡献指南](CONTRIBUTING.md) · [安全说明](SECURITY.md) · [更新日志](CHANGELOG.md)。
|
|
152
|
+
|
|
153
|
+
## 参与贡献
|
|
154
|
+
|
|
155
|
+
- 开发与提交约定见 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
|
156
|
+
- 安全问题请按 [SECURITY.md](SECURITY.md) 私下报告,不要开公开 issue。
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
MIT。终端渲染使用随包分发的 [xterm.js](https://github.com/xtermjs/xterm.js)(MIT),许可文本见 [vendor/XTERM-LICENSE](vendor/XTERM-LICENSE)。
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SSH Workbench(dsh-ssh-workbench)安全说明
|
|
2
|
+
|
|
3
|
+
## 报告漏洞
|
|
4
|
+
|
|
5
|
+
请通过 GitHub 的 **Security → Report a vulnerability** 私下报告(或直接联系维护者),不要在公开 issue 中披露未修复的安全问题。
|
|
6
|
+
|
|
7
|
+
## 设计说明
|
|
8
|
+
|
|
9
|
+
- **凭据**:使用 AES-256-GCM 加密存储在 `$DSH_HOME/ssh-workbench/secrets.json`,密钥在 `secrets.key`(0600);纳管资源清单不存明文密码。
|
|
10
|
+
- **主机指纹**:插件维护自己的 `known_hosts`,默认 `strict`(未知指纹拒绝);UI 显示 SHA256 指纹并询问是否信任,由用户决定;信任后保存。指纹变化时连接会被拒绝并提示「服务器主机密钥已变化」,用户核对后可显式「更新信任」。
|
|
11
|
+
- **审批**:插件不是权限边界,只硬阻断机器级黑名单;其余远程命令是否弹审批完全由 DSH 会话预设决定(ask / never)。当前不提供命令分级、AI 风险解释或审计。
|
|
12
|
+
- **黑名单是 best-effort**:`;`、`&&`、`|`、单个 `&`、换行都会逐段检查;每段会先按 shell 语义还原(去掉引号/反斜杠、剥离 `sudo`/`timeout`/`env`/`!`/赋值等包装、路径词法规范化/glob 前缀、`$()`/反引号/`eval` 递归),所以 `"mkfs.ext4"`、`\rm -rf /`、`rm -rf /etc/`、`cat > "/dev/sda"`、`echo "$(mkfs...)"` 都会命中。但 `bash -c`、base64、脚本文件、解释器 heredoc 正文不会被解析,真正的安全边界仍是 SSH 最小权限 + host-key 固定 + 网络隔离 + DSH 审批。
|
|
13
|
+
- **本地↔远端传输**(右侧栏文件面板的 SFTP 上传/下载)以 DSH 宿主进程的 OS 权限读写本地文件;请把宿主账号视为可信。
|
|
14
|
+
- **用户终端**:远程工作台的终端是用户主动输入,不经过 agent 的审批、沙箱或黑名单;远程终端使用同一份 SSH 凭据与主机校验,本地终端以 Host 进程权限运行。终端会话随页签/页面关闭而结束,并受空闲回收约束。
|
|
15
|
+
- **本地文件管理**:工作台的本地文件浏览默认限制在宿主用户主目录内(插件配置 `localRoot` 可改为其他绝对路径),解析真实路径后拒绝越界与符号链接逃逸;它不是模型工具,也不暴露给 agent。
|
|
16
|
+
- **远程 shell 绕过本地沙箱**:远程命令在服务器上执行,不受 DSH 本地文件沙箱约束(macOS/Linux 宿主的 POSIX 目标经原生 `bash` 路由,Windows 宿主的 POSIX 目标经 `remote_bash`,Windows 目标在任一宿主上都经 `remote_pwsh`);请用最小权限 SSH 账号并保持 host-key `strict`。
|
|
17
|
+
- **依赖**:发布包没有安装期运行时依赖;SSH 传输使用随包携带的纯 JS `ssh2` 1.17.0 及其依赖(版本与许可证见 `vendor/NOTICE.md`)。这样做避免了插件安装时执行第三方原生构建脚本,但意味着 ssh2 的安全更新需要随插件版本一起发布;维护者应定期跟进上游安全公告并升级 vendor 副本。
|
|
18
|
+
- **Windows 目标黑名单**:`remote_pwsh` 使用单独的 PowerShell 规则集(`Format-Volume`、`Clear-Disk`、`diskpart`、`bcdedit`、`cipher /w`、卷影删除、整盘递归删除等);同样只是防误操作的 best-effort,不是权限边界。
|
|
19
|
+
|
|
20
|
+
## 运维建议
|
|
21
|
+
|
|
22
|
+
- 给插件使用独立的最小权限 SSH 账号;host-key 保持 `strict`。
|
|
23
|
+
- 生产服务器优先使用 `ask` / 自动审查预设;`完全权限` 只在受控环境使用。
|
|
24
|
+
- 重要变更前先备份;黑名单不能替代备份。
|
|
25
|
+
- 不要提交 `servers.json`、`secrets.json`、`secrets.key`、`known_hosts` 或活动日志。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# SSH Workbench(dsh-ssh-workbench)架构(v1.6.4)
|
|
2
|
+
|
|
3
|
+
> 产品定位与用法见 [README.md](../README.md);本文只讲实现分层。
|
|
4
|
+
|
|
5
|
+
## 分层
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
lib/
|
|
9
|
+
├── index.js 插件入口:Config、apply、工具注册(ssh_workbench_target + 按宿主/方言出现的 remote_*)
|
|
10
|
+
├── routes.js UI 数据面:资源管理 / 连接测试 / SFTP 文件面板 / 侧边栏偏好
|
|
11
|
+
├── client.js Client 半片:左侧导航远程工作台、设置页、@ 引用 chip、右侧栏文件面板
|
|
12
|
+
└── core/
|
|
13
|
+
├── targets.js 每会话目标绑定:@ 解析、切换、历史回放
|
|
14
|
+
├── server-reference.js agent/pre-step:绑定 + 注入目标上下文
|
|
15
|
+
├── remote-bash.js tools/execute:把原生 bash 路由到 SSH,映射原生输出值
|
|
16
|
+
├── remote-bash-tool.js 插件自有 remote_bash / remote_pwsh 工具(Windows 宿主与 Windows 目标)
|
|
17
|
+
├── shell-adapters.js 方言适配器入口:POSIX 适配器、按方言选择、宿主平台判断
|
|
18
|
+
├── win32-adapter.js Windows 适配器:PowerShell -EncodedCommand、UTF-8、退出码、workdir
|
|
19
|
+
├── dialect.js 目标方言:facts.dialect 优先、platform 仅作提示
|
|
20
|
+
├── guard.js ctx.tools.guard:危险命令黑名单(只 deny,按工具路由规则集)
|
|
21
|
+
├── gate.js POSIX 命令黑名单规则与分类
|
|
22
|
+
├── gate-pwsh.js PowerShell 命令黑名单规则与分类
|
|
23
|
+
├── background.js 后台任务:POSIX nohup / Windows Start-Process 启动器、pid/日志标记解析与展示
|
|
24
|
+
├── posix-quote.js POSIX 单引号转义(路由与后台启动器共用)
|
|
25
|
+
├── store.js 服务器清单与持久化
|
|
26
|
+
├── secrets.js 密码/私钥口令(0600,本机密钥加密)
|
|
27
|
+
├── known-hosts.js 主机身份校验与信任记录
|
|
28
|
+
├── broker.js 连接池、通道池、超时/取消/输出截断
|
|
29
|
+
├── ssh.js runtime 门面:exec / test / warm / SFTP
|
|
30
|
+
├── errors.js 错误分类与建议
|
|
31
|
+
├── activity.js UI 概览用本地操作记录(非审计)
|
|
32
|
+
├── prefs.js 侧边栏等 UI 偏好(~/.dsh/ssh-workbench/prefs.json,0600)
|
|
33
|
+
├── terminals.js 交互终端会话:远程 SSH shell + 本地 PTY,缓冲/轮询/空闲回收
|
|
34
|
+
├── local-file-api.js 本地文件 API:以合成 __local__ 资源复用同一条 /sftp/* 路由面
|
|
35
|
+
├── localfs.js 本地根目录(默认用户主目录,可用 localRoot 配置)内的文件浏览与写入(realpath 规范化;越界/符号链接写入与删除防穿透)
|
|
36
|
+
└── paths.js 数据目录与私有文件写入
|
|
37
|
+
|
|
38
|
+
vendor/
|
|
39
|
+
├── xterm.js 终端渲染构建输入(xterm.js UMD,MIT;实际已内联进 lib/client.js,无运行时路由)
|
|
40
|
+
├── ssh2/ 纯 JS SSH 传输实现(MIT,随包携带;broker.js 直接 import)
|
|
41
|
+
└── node_modules/ ssh2 的纯 JS 运行时依赖(asn1 / bcrypt-pbkdf / safer-buffer / tweetnacl)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`ssh2` 不通过 `dependencies` 安装,而是以纯 JS 形式 vendor 进发布包(`vendor/ssh2` + `vendor/node_modules/`);broker 用相对路径动态 import。这样插件安装不触发 `node-gyp`、不需要本机编译工具链、也不依赖 npm 网络,代价是包体积略大。ssh2 的可选原生模块(`cpu-features`、`nan`、`sshcrypto.node`)全部未携带,ssh2 会回退到纯 JS 实现。
|
|
45
|
+
|
|
46
|
+
## 一次远程 bash 的完整路径
|
|
47
|
+
|
|
48
|
+
1. 用户消息进入 `agent/pre-step`。
|
|
49
|
+
2. `server-reference.js`:
|
|
50
|
+
- 从宿主消息里提取 `@名字`,匹配服务器清单;
|
|
51
|
+
- 1 个 → 绑定为 active target;多个 → 记住候选并要求模型用 `ssh_workbench_target` 选择;
|
|
52
|
+
- 需要时注入一条 user-role 目标上下文(source kind `ssh-workbench-target`),并 spread 下游 decision。
|
|
53
|
+
3. 模型调用原生 `bash`。
|
|
54
|
+
4. DSH 审批(本插件不参与)。
|
|
55
|
+
5. `ctx.tools.guard()`(`guard.js`):若本会话有 active target 且命令命中黑名单 → 直接拒绝。`gate.js` 先把每段还原成 argv words(去引号/转义、剥 `sudo`/`timeout` 等包装、路径规范化、重定向按 token、`$()`/`eval` 递归)再匹配。
|
|
56
|
+
6. `tools/execute` waterfall(`remote-bash.js`;仅 POSIX 宿主、仅 POSIX 目标):
|
|
57
|
+
- 非 `bash` / 无目标 → `next()`(本地行为不变);`@a @b` 后未选目标 → `TARGET_NOT_SELECTED` 错误,不静默跑本地;
|
|
58
|
+
- `run_in_background` → 结构化错误(远程不支持);
|
|
59
|
+
- 处理 `workdir`(绝对路径 / `~` / 相对路径 → `$HOME` 前缀);
|
|
60
|
+
- 探测远端 `timeout` 能力(`kill`/`basic`/`none` + 登录 shell 路径,按服务器缓存),可用时把命令包成 `timeout [-k N] <秒> '<shell>' -c '<命令>'`,让客户端超时同时终止远端进程组;
|
|
61
|
+
- `runtime.exec(server, command, { timeoutMs, signal, cap, stderrCap })`;broker 建通道后立即关闭 stdin(等价 `</dev/null`),把远端 `timeout` 的 exit 124 映射回 timeout 结果,并对 stdout/stderr 分别限长;
|
|
62
|
+
- 映射成原生 bash foreground value,或结构化错误结果;value 的 cwd 带目标前缀(`web-1:/var/log`);超时/取消结果在 stderr 说明远端是否已终止;目标切换后的首条命令追加 `[remote] target` 行。
|
|
63
|
+
7. DSH 管道用原生 bash 的输出 schema 校验、原生 renderer 渲染终端卡片。
|
|
64
|
+
|
|
65
|
+
## 多宿主与多方言(v1.5)
|
|
66
|
+
|
|
67
|
+
DSH 的内置 shell 工具按宿主平台二选一:POSIX 宿主有 `bash`、没有 `pwsh`;Windows 宿主有 `pwsh`、没有 `bash`。因此“谁是远程执行入口”由宿主与目标方言共同决定:
|
|
68
|
+
|
|
69
|
+
| 宿主 \ 目标 | POSIX | Windows |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| macOS/Linux | 原生 `bash`(`tools/execute` 路由,保原生卡片) | 插件自有 `remote_pwsh` |
|
|
72
|
+
| Windows | 插件自有 `remote_bash` | 插件自有 `remote_pwsh` |
|
|
73
|
+
|
|
74
|
+
- 目标方言由连接后的探测决定(`uname -s` 成功 → posix;否则 `cmd /c ver` 成功 → windows),写入 `facts.dialect`;`platform` 字段只作探测前提示。`effectiveDialect()` 是唯一读取入口。
|
|
75
|
+
- 方言决定命令构造:POSIX 用 `cd -- ... && ...` + 可选 `timeout` 包装;Windows 用 UTF-16LE base64 的 `powershell -EncodedCommand` 脚本(内含 UTF-8 输出、`Set-Location`、显式退出码),没有远端 `timeout`。
|
|
76
|
+
- 目标上下文与 `ssh_workbench_target` 文案按方言/宿主生成正确的工具名;`remote_bash` 与 `remote_pwsh` 互相拒绝错误方言并给出改用建议。
|
|
77
|
+
- `ctx.tools.guard()` 按工具名选择 POSIX 或 PowerShell 规则集。
|
|
78
|
+
|
|
79
|
+
## 后台任务(v1.6)
|
|
80
|
+
|
|
81
|
+
`run_in_background: true` 不再报错,而是启动一个**脱离 SSH 会话**的远端进程:
|
|
82
|
+
|
|
83
|
+
- POSIX:`sh -c '<脚本>'` 内用 `nohup "$SHELL" -lc` 启动命令,stdout/stderr 重定向到 `mktemp /tmp/dsh-ssh-workbench-bg.XXXXXX` 生成的日志;启动器打印 `__SDH_BG_PID__` / `__SDH_BG_LOG__` 标记。
|
|
84
|
+
- Windows:外层 PowerShell 用 `Start-Process -RedirectStandardOutput/-RedirectStandardError -WindowStyle Hidden -PassThru` 启动内层编码脚本,输出 `__SDH_BG_PID__` / `__SDH_BG_LOG__` / `__SDH_BG_ERR__`。
|
|
85
|
+
- 工具/路由解析标记后返回 pid、日志路径与读取/停止命令;启动失败(没有 pid)返回 `REMOTE_BACKGROUND_FAILED`。
|
|
86
|
+
- 远端进程不在 DSH 本地 `job_*` 注册表里:`job_output` 看不到它,模型用 `tail` / `Get-Content` 取输出、`kill` / `Stop-Process` 停止;`timeoutMs` 与取消只作用于启动调用。
|
|
87
|
+
|
|
88
|
+
## 关键契约(来自 DSH,非本插件发明)
|
|
89
|
+
|
|
90
|
+
- `tools/execute`:`(exec, next) => ToolExecutionResult`,返回 `{ value }` 替换执行;官方插件 `dsh-tool-call-timeout-policy` 同款用法。
|
|
91
|
+
- `agent/pre-step`:返回 `{ kind: 'enter', messages }`,改写必须 spread。
|
|
92
|
+
- `ctx.tools.guard()`:同步、单调的拒绝;在审批之后执行。
|
|
93
|
+
- 原生 `bash` 输出值:`{ kind:'foreground', cwd, exitCode, signal, timedOut, aborted, timeoutMs, stdout, stderr }`。
|
|
94
|
+
- 模型可见工具:`ssh_workbench_target` 恒在;POSIX 宿主上另有 `remote_pwsh`,Windows 宿主上另有 `remote_bash` + `remote_pwsh`。
|
|
95
|
+
|
|
96
|
+
## 目标状态生命周期
|
|
97
|
+
|
|
98
|
+
- 存储:进程内 `Map<sessionId, {candidates, active, version, injectedVersion, seeded}>`。
|
|
99
|
+
- 来源:人类消息里的 `@`(权威、可回放)+ `ssh_workbench_target` 工具。
|
|
100
|
+
- 恢复:会话恢复后首次 `agent/pre-step` 用 `session.deriveMessages()` 回放历史人类消息。
|
|
101
|
+
- 清理:`agent/disposed` 或插件卸载。
|
|
102
|
+
|
|
103
|
+
## 降级行为
|
|
104
|
+
|
|
105
|
+
| 情况 | 行为 |
|
|
106
|
+
|---|---|
|
|
107
|
+
| 没有目标 | 原生工具完全本地,零开销 |
|
|
108
|
+
| `targetContext:false` | 不绑定、不注入;`ssh_workbench_target` 仍可手动使用 |
|
|
109
|
+
| `ctx.tools.guard` 不可用(旧 DSH) | 记录 warning,黑名单关闭,其余功能不变 |
|
|
110
|
+
| 目标被删除/禁用/方言不匹配 | 返回结构化错误,提示重新选择目标或改用另一种 remote 工具 |
|
|
111
|
+
| 远端没有 `timeout` 工具 | 命令不加包装;超时只停止等待,stderr 提示远端可能仍在运行 |
|
|
112
|
+
| 非 ASCII 服务器名 | host/client 两侧都支持 Unicode 名称;`@测试机` 可直接绑定 |
|
|
113
|
+
| host facts 采集失败 | 只影响 UI/上下文摘要,不影响执行;下次测试/选中目标时重试 |
|
|
114
|
+
| SFTP 分块卡死 | `transferChunkTimeoutMs` 到点关闭会话并报 `SFTP_TIMEOUT`,UI 可从 offset 续传 |
|
|
115
|
+
| 远程 home 解析失败 | `/sftp/home` 返回可读错误,工作台文件面板回退到 `/` |
|
|
116
|
+
| 多个 `@` 未选择目标 | router 返回 `TARGET_NOT_SELECTED`,避免静默在本地执行 |
|
|
117
|
+
| 服务器清单损坏 | 路由返回错误结果,不影响本地工具 |
|
|
118
|
+
|
|
119
|
+
## 安全边界
|
|
120
|
+
|
|
121
|
+
- 黑名单只拦机器毁灭类命令,不是权限边界。
|
|
122
|
+
- 远程命令不受 DSH 本地沙箱约束;是否审批由 DSH 会话预设决定。
|
|
123
|
+
- 凭据与主机身份:见 `secrets.js` / `known-hosts.js`;未知指纹不会被静默信任。
|
|
124
|
+
- 插件不写 Session 事件、不做审计日志;`activity.json` 只是 UI 概览。
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# SSH Workbench(远程工作台)— 快速上手
|
|
2
|
+
|
|
3
|
+
## 1. 安装
|
|
4
|
+
|
|
5
|
+
在 DSH 的 **设置 → 插件** 里搜索 `dsh-ssh-workbench` 安装。也可以从源码构建:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd dsh-ssh-workbench
|
|
9
|
+
npm test
|
|
10
|
+
npm run pack
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
然后安装 `dist/dsh-ssh-workbench-1.6.4.tgz`。安装后重启/重载插件。
|
|
14
|
+
|
|
15
|
+
发布包自带纯 JS 的 SSH 依赖,安装过程不需要编译(不需要 Xcode Command Line Tools)、也不额外下载 npm 包,离线机器同样可以安装。
|
|
16
|
+
|
|
17
|
+
## 2. 添加纳管资源
|
|
18
|
+
|
|
19
|
+
**设置 → 远程工作台**:
|
|
20
|
+
|
|
21
|
+
- 手动添加:名称、目标地址、SSH 端口、登录用户名、默认 Shell、认证方式(密码 / 私钥)、描述、是否启用;
|
|
22
|
+
- 密码类认证在表单里设置密码(存本机加密文件);私钥认证填本机私钥路径;
|
|
23
|
+
- 首次连接会显示主机指纹并询问是否信任;信任后保存该指纹,以后若主机密钥变化会拒绝连接。
|
|
24
|
+
- 建议先点「测试连接」确认连通。
|
|
25
|
+
|
|
26
|
+
## 3. 开始使用
|
|
27
|
+
|
|
28
|
+
在对话里先 `@资源名`,再正常描述任务:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
@web-1 看下磁盘和内存
|
|
32
|
+
@web-1 把 /etc/nginx/nginx.conf 的 worker_connections 改成 2048,然后 nginx -t
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
模型会调用原生 `bash`(Windows 宿主上是 `remote_bash`),命令实际在 web-1 上执行;POSIX 宿主的结果卡片与本地 bash 一致(退出码、超时、截断)。
|
|
36
|
+
|
|
37
|
+
## 4. 多目标
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
@web-1 @db-1 各自看下磁盘
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
模型会先调用 `ssh_workbench_target({ server: "web-1" })` 再执行,然后切换到 `db-1`。可以随时用 `ssh_workbench_target({ server: "local" })` 回到本机。
|
|
44
|
+
|
|
45
|
+
注意:一次提到多个资源后,当前目标会先被清空;在模型调用 `ssh_workbench_target` 选择之前,直接调用远程 shell 工具(POSIX 宿主上的原生 `bash` 或 `remote_bash`)会返回 `TARGET_NOT_SELECTED` 错误(不会静默在本机执行)。资源名支持中文/非 ASCII(如 `@测试机`)。
|
|
46
|
+
|
|
47
|
+
## 5. 远程工作台
|
|
48
|
+
|
|
49
|
+
**左侧导航 → 远程工作台** 是一个独立页面:左边终端,右边文件管理,中间分隔条可拖动。
|
|
50
|
+
|
|
51
|
+
- 终端:点「+」新建 **本地终端** 或选择一台远程资源开 **远程 SSH 终端**;每个页签一个会话,关闭页签即结束会话。只有活动页签在后台读取输出,切回其他页签时会从上次位置补齐,不会丢输出。
|
|
52
|
+
- 文件:跟着当前终端页签走 —— 本地终端时显示 **本地用户主目录文件**(默认 `$HOME`,可用插件配置 `localRoot` 指定其他绝对目录),远程终端时显示该资源的 **SFTP 文件**(远程默认打开登录用户的 home)。两类文件都支持浏览/**在工作台内直接单击预览**/下载/上传/重命名/删除/新建文件夹,远程文件还有传输记录与续传。
|
|
53
|
+
- 本地文件范围限定在 `localRoot`(默认用户主目录)及其子目录,面包屑显示真实路径;越界路径与指向外部的符号链接会被拒绝,需要操作根目录以外的本地路径时用本地终端。
|
|
54
|
+
- 页面刷新/关闭会尽力关闭终端会话;进程异常退出时服务端会话会在空闲 30 分钟后回收。
|
|
55
|
+
|
|
56
|
+
如果不想在左侧导航看到它:**插件管理 → 远程工作台** 页面里关闭「在侧边栏显示远程工作台」。关闭后左侧导航不再出现入口,右侧栏的「远程工作台 / 远程文件」页签、`@资源名` 远程执行、设置页与模型工具都不受影响。
|
|
57
|
+
|
|
58
|
+
## 6. 常见问题
|
|
59
|
+
|
|
60
|
+
**为什么 `read` / `write` / `edit` 读不到远程文件?**
|
|
61
|
+
这些文件工具始终作用于 DSH 主机(POSIX 宿主上的原生 `bash` 或远程 shell 工具都不会改变这一点),误用 `write` 会写到本机。远程文件用对应的远程 shell 工具操作(POSIX 目标:`cat`、`tee`、`sed`;Windows 目标:`Get-Content`、`Set-Content`),或用右侧栏 SFTP 面板。
|
|
62
|
+
|
|
63
|
+
**命令很慢/超时?**
|
|
64
|
+
远程命令默认 120s,可用远程 shell 工具的 `timeoutMs` 参数(原生 `bash` / `remote_bash` / `remote_pwsh`)或插件配置 `commandTimeoutMs` 调整。连接池会复用连接,第一次会稍慢。超时后如果远端有 `timeout`,整个远端进程组会被终止(TERM 后按 `timeoutKillAfterMs` 再补 KILL);没有 `timeout` 的服务器(如 macOS)只能停止等待,命令可能还在跑,结果 stderr 会提示这一点。**取消(Esc)不会立即杀远端**,远端仍会计时到自己的 deadline。
|
|
65
|
+
|
|
66
|
+
**为什么 `cat` / `read` 这类命令立刻结束了?**
|
|
67
|
+
远程命令的 stdin 在启动后立即关闭(等价 `</dev/null`),读 stdin 的命令会立刻得到 EOF,不会挂到超时。
|
|
68
|
+
|
|
69
|
+
**怎么确认命令跑在哪台机器?**
|
|
70
|
+
目标切换后的第一条远程命令会带有目标提示(原生 bash 卡片显示 stderr 行与 cwd 前缀,如 `[remote] target: web-1 (...)`、`web-1:/var/log`;远程 shell 工具在结果文本里带 target/cwd);composer 下方参数行常驻显示当前目标。也可以点 `ssh_workbench_target` 选 `local` 回到本机。
|
|
71
|
+
|
|
72
|
+
**怎么跑长时间任务 / 后台服务?**
|
|
73
|
+
让模型带 `run_in_background: true` 调用远程 shell 工具(`remote_bash` / `remote_pwsh`,POSIX 宿主上的原生 `bash` 路由同样支持)。工具会立刻返回远端 pid 和日志路径:
|
|
74
|
+
- POSIX:`tail -f <log>` 看输出,`kill <pid>` 停止;
|
|
75
|
+
- Windows:`Get-Content -LiteralPath '<log>' -Wait` 看输出,`Stop-Process -Id <pid> -Force` 停止。
|
|
76
|
+
后台进程与本次工具调用脱离,调用返回后继续运行;`timeoutMs` 只约束启动调用本身。它不是 DSH 本地 job,`job_*` 工具看不到它。
|
|
77
|
+
|
|
78
|
+
**资源列表里的 Linux / Windows 徽标是什么?**
|
|
79
|
+
连接后自动探测到的目标平台(`uname -s` / `cmd /c ver`),不是表单里手填的 `platform`;测试连接的结果里也会显示。旧资源第一次连接前显示的是提示值,探测完成后自动更新。
|
|
80
|
+
|
|
81
|
+
**危险命令被拒?**
|
|
82
|
+
`rm -rf /`、`mkfs`、`dd of=/dev/*`、分区工具、改根目录权限等会被黑名单直接拦截;引号/反斜杠、路径变体(尾斜杠、`//`、`..`)、`$()`/`eval` 都会先还原再判断。这是兜底,不是权限边界;`bash -c`、base64、脚本文件等仍可能绕过,其他命令由 DSH 审批预设决定是否询问。
|
|
83
|
+
|
|
84
|
+
**服务器重装了 / 主机密钥变了,连不上?**
|
|
85
|
+
连接会被拒绝并显示「服务器主机密钥已变化」,同时给出原指纹和新指纹。确认是你自己重装、迁移或更换了服务器后,点「更新信任」即可;如果不是你做的变更,先别信任,可能是中间人攻击或误连了别的机器。
|
|
86
|
+
|
|
87
|
+
**Windows 服务器?**
|
|
88
|
+
需要先在 Windows 目标上启用 OpenSSH Server(系统可选功能,管理员 PowerShell:`Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0`,然后 `Start-Service sshd`、`Set-Service -Name sshd -StartupType Automatic`)。插件连接后会探测方言,Windows 目标经 `remote_pwsh` 执行 PowerShell 命令;建议把默认 shell 设为 PowerShell。文件面板/连接测试/SSH 终端不受影响。
|
|
89
|
+
|
|
90
|
+
**方言(POSIX / Windows)要手动填吗?**
|
|
91
|
+
不用。连接测试或选中目标时会执行 `uname -s`(POSIX)和 `cmd /c ver`(Windows)探测,结果写入 `facts.dialect`,之后自动选择 `remote_bash` / `remote_pwsh` 与对应上下文。清单里的 `platform` 字段只是探测前的提示值。
|
|
92
|
+
|
|
93
|
+
**Windows 上的 DSH 宿主?**
|
|
94
|
+
Windows 版 DSH 没有内置 `bash`(DSH 按平台禁用),插件会在该宿主上注册自有的 `remote_bash` 工具用于 POSIX 目标;用法与 POSIX 宿主上的原生 `bash` 路由一致(`@资源名`、`workdir`、`timeoutMs`),原生的 `pwsh` 始终保持本机语义。Windows 目标在两种宿主上都走 `remote_pwsh`。
|