Repository navigation
ells v0.2.0
ells v0.2.0
一键安装 / Install
macOS / Linux:
ELLS_VERSION=v0.2.0 curl -fsSL https://raw.githubusercontent.com/lg10/ells/main/install.sh | shWindows PowerShell:
$env:ELLS_VERSION="v0.2.0"; irm https://raw.githubusercontent.com/lg10/ells/main/install.ps1 | iex安装脚本会强制校验 SHA256SUMS.txt。产物:ells-linux-x86_64 · ells-macos-universal(x86_64 + Apple Silicon 合一)· ells-windows-x86_64.exe · SHA256SUMS.txt
[0.2.0] - 2026-10-10
安全
- 保存凭据不再原地覆写:
vault.bin、settings.ini、known_hosts、主密码副本
~/.ells/.master全部改为"同目录临时文件 → 写全 → fsync → rename"。原先的
create(true).truncate(true)在写一半时崩溃或断电会留下半截文件,而保险库损坏
等于主机与密码无法挽回(主密码不可能重建)。Unix 下临时文件同样收 0600。
新增
~/.ssh/config双向:导入现在认LocalForward/RemoteForward/
DynamicForward(含[bind:]port:host:hostport与 IPv6[::1]:6379这类带冒号的
目的端),通配段的转发按默认值下发;新增导出功能把保险库写成 ssh 配置片段,
导出里绝不出现密码(密码留在vault.bin)。- 端口转发内核:每台主机一条 SSH 连接承载它的全部规则,本地监听口在拨号之前
绑定并跨重连持有(掉线期间端口不被抢走,来连的请求排在 backlog 里等),失败按
[1,2,5,15,30,60]秒退避并封顶。-L与-D(SOCKS5,无认证)已实现;-R的规则
可以存库与往返导入,但会明确报告"暂不支持"而不是假装工作。 - 无头 CLI:
ells list(--format table|json、--filter)、ells exec <别名> -- <命令>
(--tty/--timeout/--stdin,远端退出码原样透传)、ells sftp ls|get|put|rm|chmod、
ells tunnel <别名>|--all(只起转发并常驻)、ells export [--out]、ells completions bash|zsh|fish。退出码是对外契约:0成功 ·1失败 ·2用法或安全闸门(差一个
--yes、删目录没给--recursive,原因用中文打到 stderr)·124超时。主密码经
ELLS_MASTER或 stdin 第一行传入,任何密码、私钥内容、主密码都不会被打印,
--format json里只有可公开的元数据;-y只放行首次密钥,密钥变更照样拒绝。 - 隧道管理器界面:列表页
t打开,每台一行▲已就绪 /◐连或重连中 /▼失败,
空格/s就地启停、Enter进规则表格改规则,x全停;隧道不随会话标签关闭而死,状态变化写进操作记录。 - 主机组织:表单新增「分组」「标签」「转发」三栏,默认列表排序为 分组 → 组内收藏 →
组内最近使用 → 别名(o可换档);f加星置顶,/之后直接打字做模糊过滤(别名、主机、用户、
分组、标签、备注都算命中,#标签精确命中)。 - 操作记录:连接 / 断开 / 连接失败、主机密钥被信任或变更、每一次传输、隧道状态、
保险库保存、导入导出、改主密码都追加进~/.ells/audit.log(北京时间、只追加、
超 1 MiB 保后半转存)。记录写入前抹掉控制字符与换行,防止远端字符串往日志里塞假记录。
列表页l直接翻看,不用出界面。 - 会话落盘:每建立一路会话把终端原始字节另存
~/.ells/logs/<别名>-<时间>.log
(保留 ANSI,事后less -R照样带色),单份 8 MiB 封顶、启动时清理 30 天前的旧件;
列表页v打开面板看列表(Enter进正文,控制序列已剥掉,d删单份),开关在
「设置 → 会话记录」。 - 已知主机密钥面板:
h列出~/.ells/known_hosts(ells 自己记的,d可删,删掉
下次连重新问指纹)与~/.ssh/known_hosts(只显示,永不改动)。 - 断线自动重连:非人为断开按指数退避自己接回去——
initial * 2^(n-1)、封顶
max_delay_ms、只往上加的抖动(不引入rand,用纳秒与 pid 混出的伪随机量);
连着超过reconnect_stable_secs才算"稳了",下次掉线重头计次。排队时状态行写明
"N 秒后自动重连(第 n/m 次)· 按 Ctrl-] 停止",每一路带代号,用户自己断开、关标签
或手动重连后旧定时器立即作废。主机密钥被拒不是网络问题,永不自动重试。次数上限在
「设置 → 自动重连」按Enter在关 → 1 → 2 → 3 → 5 → 无限间循环,←→微调。 - 远端
chmod:浏览器c与ells sftp chmod <别名> 600 /path共用一份八进制解析
(644/0644/0o644/0/0000都合法,7778、abc、空串给中文报错),
只送权限位——属主、大小、时间戳一概不动。 - 列表页
x导出 ssh_config:落点固定~/.ells/ssh_config.export(原子写),确认框里
先说清写几台、写到哪、不含密码;~/.ssh/config本体任何路径下都不写。 a新增带模板:列表里选中一台时按a,把它的用户 / 端口 / 认证方式 / 私钥路径 /
跳板 / 分组 / 标签 / 转发带进新表,但别名、主机名和密码 / 私钥口令一律留空——
结构可以复用,身份和凭据必须自己填(这条有单测兜着)。- 列表页按分组分段:每个分组一个段头
▾ 生产 (3),Space折叠/展开光标所在那一段,
z一键收起全部或全部放出(全折叠时列表只剩段头,正好数清自己有几组)。折叠只在真的
按分组排的时候生效:一进过滤就收起段头、折叠一并失效,免得"明明搜到了却看不见"。
段头的计数连被折起来的那些一起算,展开前后数字不变。 o循环排序四档:默认(分组 → 组内收藏 → 组内最近使用 → 别名)· 最近使用 · 别名 ·
分组(组内只按别名)。选中的那档写进settings.ini的list_sort=,下次启动还是它。- 每行右端一列「最近使用」:
刚刚 / 5分 / 3小时 / 昨天 / 5天 / 2月 / 从未,相对时间按
字符对齐在行尾。哪台还在手上过,不用再点进去猜。 - 过滤命中可视化:面板标题写
命中 n/m,别名里被命中的那几个字符点亮(按下标切段,
汉字不会被切成半截)。 - 表单必填标记:别名 / 主机 / 用户三项前面打
*,提交失败时只点缺的那几项的名,
不再一句"别名、主机、用户是必填项"把已经填对的也重报一遍。 Ctrl-R让口令显形:光标在「密码」或「私钥口令」上按一次就明文显示,再按遮回去。
十次"存完连不上"有八次是密码末尾多敲了一个字符,之前只能反复重填。- 「分组」栏行内提示:光标停在这一栏时,下面列出已有分组及各自台数,并说清这次是
「归入生产」还是「将新建 xxx」——「生产」「生产 」这种只差空格的写法从此合并成同一段。 - 端口转发规则表格编辑器:隧道面板里按
Enter(列表页按p)进表格,一行一条规则、
五列对着填——类型 / 绑定 / 本地端口 / 目标主机 / 目标端口。↑↓移行、←→/Tab移格
(第 1 列上←→循环L/D/R)、Ctrl-N加行、Ctrl-D删行、Ctrl-C清空当前格、
Enter保存、Esc放弃。逐行报错并带表里的行号,只点缺的那一格的名;隧道正在跑就按
新规则自动重启,规则清空则顺手停掉。 - 本地端口可以留空 = 交给系统分配(与
ssh -L 0:db:5432同义):两台 SSH 链接都想占物理机
8080 时,其中一台留空就不互挤。表单的「转发」栏也能只写目标(-L db:5432)。存盘仍是
listen_port: 0,保险库格式与ssh_config往返都不变。 - 「端口映射」总表(
m,或点隧道面板顶部那个按钮):主机 / 规则 / 实际监听 / 状态四列,
自动分配最后落在哪个口只在这里看得见(标「(自动)」)。隧道每次状态变化都带上自己
实际绑上的地址端口,停止即从总表消失,不会留一个已经不存在的口。 - 撞口不再靠猜:编辑时同一口的行尾标
⚠并在表下点名"与 db-prod、本表第 2 行 同用 8080 —
留空本地口即可自动分配";隧道面板顶部直接写⚠ 8080 被多台主机共用;真去绑定时失败原因
说清是谁占着(另一台 ells 主机的哪条规则),没有别人占就明说是外部程序。写死的端口绝不偷偷
换号——只提示、只报因。 ells tunnel每行状态都带着实际绑上的本地端口,它同时就是"这条 db 到底开在哪个口"的查询命令。- 会话页底部一行远端主机指标:CPU / 内存 / 磁盘三根进度条带整数百分比,磁盘取用得最满的那个
真实挂载点,比例直接照抄df的 Capacity 列(自己算会和df差几个点,用户一对照就认为 ells
在编数字),旁边补一句挂载点和已用/总量;1/5/15 分钟平均负载同排(摆得下才写 ——
占用和排队是两件事,8 核机器上 CPU 50% 很闲、负载 24 已经在挤)。这两句补充的话一律排在整行末尾,
三格本身只有标签、进度条和百分比:挂在各自那一格后面会把那一格撑得比旁边的宽,用户第一眼
看到的是"这根条怎么长一点"而不是数变了没有。数据走的是那条已经认证好的
连接:优先在它已有的 SFTP 会话上读/proc/stat、/proc/meminfo、/proc/loadavg、/proc/mounts,
磁盘用statvfs@openssh.com问本地盘(网络盘一律不问 —— 一次卡在失效挂载点上的 statvfs 会把整条
SFTP 会话拖住,文件传输跟着停);没有 SFTP、服务器不支持那个扩展或读不到东西时,回落一条一次性
exec只读通道(df -Pk),且只填还空着的那几格(CPU 靠两次快照做差,混进另一个来源的基线就成了
一条没意义的斜线)。不重做 TCP + 握手 + 认证、不碰用户正在敲的那个 PTY、远端不留进程。默认开,
节奏是分频的:/proc那三样 5 秒一轮,磁盘那一格也 5 秒一换,但中间那些轮只对「上次普查里最满
那块」问一次statvfs(挂载点表缓存在这条连接上,一个往返),普查(重读/proc/mounts、逐块问、
重新决定谁最满)60 秒才走一次 —— 逐块问盘是代价最大的一条腿,而挂载点集合一分钟里几乎不动。
没有statvfs@openssh.com的服务器上,跟单轮一个请求都不发、那一格沿用上次的数,df只在 60 秒的
普查点兜底 —— 否则那一格会把 60 秒的节奏悄悄退化成每 5 秒 fork 一个 shell(缓存的价值正在这一条)。
连上的第一轮就是普查,不必等一分钟。没在看的标签降到 60 秒一轮 —— 八个标签
一起开着时每台服务器看到的是"一分钟一次",而不是"每五秒八次";切回它那一格当场重采一轮。首帧不等:
SFTP 子系统本来就在connect()里先于 PTY 开好,所以连上立刻跑第一轮,内存、磁盘、负载当场有数;
CPU 必须两次快照做差才是瞬时值,拿到基线的那一轮之后单独用两秒接力,进去约两秒见第一个数(没有
/proc/stat的机器永远不会cpu_pending,不会两秒一次空转),之后回到 5 秒一轮;FreeBSD、精简容器
那一格一直是—而磁盘照常。采不到一律画
—,绝不折成0%;连续三轮什么都拿不到就判定这台不支持,停掉轮询、把这一行还给终端。两类失败
分开对待:通道级失败(超时、开不了通道、执行报错)说的是"这会儿采不到",不判死,只把节奏退到
5 → 10 → 30 → 60 秒,退到顶端时状态行说一句,任意一轮拿到数就自动回到 5 秒。开关在
「设置 → 主机指标」(metrics=),关掉或打开都对已经连上的标签当场生效。底部行数由 App 一处
决定,绘制、鼠标命中与视口/PTY 尺寸同源,不会出现"画面被裁掉一行"。
变更
ells --help补齐子命令清单、退出码约定与新增的~/.ells文件;快捷键一览加上
xthlv。- 设置面板新增「会话记录」与「自动重连」两行,鼠标命中区与绘制几何同步(有单测对齐)。
- 审计新增
export事件类型;ells export的写盘同样改为原子写并记一条审计。 - 隧道面板的启停从
Enter挪到空格/s:Enter在全程序都是"进入/确认",这里过去却是
"启停",改成Enter进规则表格改规则。全程序的Enter从此只做进入/确认一件事(列表页连接、
弹窗确认、表格保存),不再在一个面板里既是开关又是编辑;面板底部键位行与帮助页同步。 - 默认排序把「分组」提到「收藏」前面(收藏仍在组内置顶、星号仍在)。段头必须每组只出现
一次,全局收藏优先会让同一组被拆成两段。保险库文件格式不动,老库直接兼容。 - 启动就看到的信息更多:品牌行写
ells 主机列表 · n 台 · k 组 · 版本,面板标题写
共 n · 排序 X · 在线 k;空库提示补上"或按 i 从 ~/.ssh/config 导入"。 - 键位行与帮助页同步了
Space/z/o与表单里的Ctrl-R、*,以及新的p规则表格、
m端口映射。
文档纠偏
- ssh-agent / Pageant 认证早已落地,从路线图移入功能清单;keepalive 可调范围按代码
实际(5–3600 秒)修正,此前写的是 15–300 秒。
修复
- 隧道面板的空格键真的能启停了:面板底部和帮助页都写着"Enter/空格 启停",代码里却只绑了
s——照文案按空格什么都不会发生。现在空格与s都启停(s留着,老习惯不断)。 #标签过滤不再永远空结果:表单和文档都说"过滤时按#标签命中",可过滤串里的井号
被当成普通查询字符,而索引里存的是裸标签名,于是带井号打头必然一个都命不中。现在剥掉
查询串开头的#(ells list --filter同一份逻辑)。- Windows 安装脚本不再把 ARM64 / 老 .NET 误判成"不支持的架构":
install.ps1原先只认
OSArchitecture = X64,Windows on ARM 装不上(其实 x86_64 产物由系统内置转译运行),
老 .NET Framework 下取值为空也会误报。现在取不到就回落PROCESSOR_ARCHITECTURE,
x86_64 直装、ARM64 装 x86_64 并提示走转译,仅 32 位或未知架构才报错。 - 规则表格里"按了
Ctrl-N还没填"的那一行不再拦保存:它的类型格默认就是L,旧判定把整行
当成"填了一半",于是新增一行反倒报"第 n 行:目标主机、目标端口不能空着"——用户根本没写过这行。 - 表格滚动后鼠标点的是看得见的哪一行:绘制按滚动窗口重排了行位置,命中测试还在用未滚动的
行号,滚两行再点第 3 行会把光标放到第 1 行上。几何与滚动窗口现在只算一次、画和点共用一份。 - 表格最后一格按
→不再把焦点推出列外(推出后高亮画不出来,打字像丢了)。 - 隧道面板顶部的「端口映射」按钮在极窄终端上不再伸出面板边框。
- 从隧道面板按
m打开的弹窗,Esc关的是弹窗不是面板:两个标记同时为真时按键先给了背后
那个面板,弹窗会留在屏幕上关不掉。叠着开的界面现在统一从最上层开始吃键(与绘制顺序一致)。 ells tunnel的"启动 …"一行改用可读写法:自动口显示-L 自动 → db:5432,不再是像填错的
-L 0:db:5432;-R的"暂不支持"报错同理。- 从已知主机密钥 / 操作记录跳回列表时会先展开目标所在分组:否则光标只会被夹到别的主机
上,看起来像"点错了机器"。 - 帮助页原先写的排序规则(收藏 → 分组 → 最近使用 → 别名)与代码不符,已按实际四种排序重写。
- 弹窗、原生文件框、直通模式关闭后不再留残影:Windows 10 上(cmd 与 Windows Terminal 都中)
关掉"连接已断开"这类弹窗后,屏幕上会留着几处文字,样式还不是原来那套。根子是 ratatui 只补
差分:它以为屏幕还是上一帧,而那片刻屏幕已经被远端(直通模式直接往 stdout 写字)或被盖上来的
窗口占过,Win10 的控制台又会把被切断的全角字留下半格残片 —— 于是"没有变化"的那些格子永远没人
重写。现在主循环盯住三次"屏幕换主":从直通切回来、原生文件框关闭、最后一层弹窗关闭,任一次都
先整屏清一遍再画(清屏同时作废差分基线,这一帧是真正的全量第一帧)。顺带Ctrl-L整屏重绘
过去只复位内嵌终端的屏幕缓冲,压根没动界面,是一句空头承诺;现在它真的整屏重画。
完整历史:CHANGELOG.md · 安全策略:SECURITY.md · 安装选项与卸载:README