1. 凌晨两点,我把第 50 个工具写进了 dotfiles
上周新到一台开发机,我在终端里跑了不到三分钟,环境就恢复成了用了五六年的样子:一套 shell 配置、一个 bootstrap 脚本、一份工具清单。同事在旁边看着说,你这也太省事了。我回了一句:不是省事,是我实在受不了每换一台机器就重新点一遍鼠标。
这几年我陆陆续续攒了大概五十个命令行工具,它们覆盖了我日常工作里绝大部分的重复劳动:找文件、翻日志、改配置、查资源、跑构建、看容器、发通知,甚至包括让 AI 帮我读代码。这篇就把这份清单完整摊开,说说每个工具我为什么留下它,哪些是刚需,哪些是锦上添花,哪些装完用一次就该卸载。不管你是刚接触 CLI 的新手,还是已经有一堆 alias 的老手,应该都能从这里挑走几个。
我想先说一个判断:单一工具好不好用,和它能不能跟别的工具拼起来,是两回事。GUI 软件的价值在于把功能做全,命令行的价值在于把动作做小。一个小动作,能被脚本调用、被管道串起来、被 CI 复现,这个价值才是我真正的依赖来源。所以这份清单里没有"功能最强大"的工具,只有在组合里最顺手的工具。
1.1 三个把我彻底推向命令行的真实场景
第一个场景是日志排查。线上出问题的时候,日志是几百个 GZ 文件拆在几十个目录里。GUI 编辑器打开一个就要卡三秒,搜索还得等索引。用zcat加rg,一条管道下去几秒钟就能把时间段内的异常抓出来,再jq一解析,字段清清楚楚。这个过程如果换成手动点,一晚上就没了。
第二个场景是环境复现。我在本地调通的构建流程,要原样搬到 CI 上跑。GUI 里的操作没法导出,只能靠截图和记忆。命令行操作天然就是文本,复制粘贴就是复现,改两个变量就能跑在另一台机器上。这个特性在多人协作里价值极大,因为你交付的不再是"我是这么点的",而是"这段脚本原封不动跑一遍"。
第三个场景是远程环境。很多线上机器只有一个 SSH 会话,没有桌面环境,没有浏览器。这时候你能用的只有终端。会几个趁手的 CLI 工具,和不带工具硬啃,效率差距可能是五倍以上。我见过有人在远程机上用vi手写几百行配置,也见过有人一条命令批量改完,区别就在这里。
1.2 我筛工具的四条硬标准
第一条是启动速度。一个工具如果启动要 200 毫秒,我一天调用两百次,就是四十秒纯等待。所以我把很多老牌工具换掉了,换成 Rust 或 Go 写的同类替代品,启动基本在 20 毫秒以内。这不是强迫症,是纯体感差异。
第二条是单一职责、能进管道。我更喜欢那种"只做一件事、输出到标准输出"的工具,因为它可以被随便串。功能大而全的工具往往有自己的交互界面和状态,很难嵌进脚本。像fzf这种东西,本身功能极简,但它把"选择"这个动作做成了可插拔的组件,价值反而最大。
第三条是维护活跃度。命令行生态里弃坑项目特别多,装一个三年前停更的工具,遇到新系统版本可能直接编译不过。我一般的判断方式是看最近半年有没有提交,issue 有没有人回。这条能帮我省掉大量试错时间。
第四条是学习成本能不能在十分钟内回本。如果一个工具需要我读半小时文档才能用出价值,我会先放一放。这份清单里的工具,绝大多数都属于"看一个例子就会用,用一次就记住"的类型。真正复杂的那些,比如kubectl、terraform,是工作本身复杂,不是工具故意为难你。
1.3 五十个工具分类速查表
下面这张表是我 dotfiles 里实际维护的清单,按用途分了六类。先说清楚:不是每个都每天用,有些是特定场景才掏出来的。你可以照着自己的工作内容挑。
| 类别 | 工具 | 我主要拿它干什么 |
|---|---|---|
| 文本与文件 | ripgrep (rg) | 全项目内容搜索,默认跳过忽略文件 |
| 文本与文件 | fd | 按名字找文件,比 find 快且好写 |
| 文本与文件 | bat | 带高亮和行号地看文件 |
| 文本与文件 | eza | 目录列表,带图标和 git 状态 |
| 文本与文件 | tree | 快速看目录结构 |
| 文本与文件 | sd | 简单直接地做文本替换 |
| 文本与文件 | jq | 解析、过滤、重组 JSON |
| 文本与文件 | yq | 处理 YAML,改清单很省事 |
| 文本与文件 | csvkit | 用命令行查 CSV,不用开表格软件 |
| 文本与文件 | pandoc | 文档格式互转 |
| 文本与文件 | ffmpeg | 音视频转码、抽帧、拼流 |
| 文本与文件 | ImageMagick | 批量改图尺寸、加水印 |
| 文本与文件 | rclone | 同步对象存储和网盘目录 |
| 文本与文件 | xargs | 把标准输出变成命令参数 |
| 导航与终端 | fzf | 把任意列表变成可搜索选择器 |
| 导航与终端 | zoxide | 用关键词跳目录,替代 cd |
| 导航与终端 | tmux | 会话保持、分屏、远程不掉线 |
| 导航与终端 | starship | 统一提示符,显示 git 和语言版本 |
| 导航与终端 | direnv | 进目录自动加载环境变量 |
| 导航与终端 | tldr | 只看命令的常用例子 |
| 导航与终端 | cheat | 自己攒的命令备忘 |
| 导航与终端 | watch | 定时重复执行并刷新输出 |
| 导航与终端 | entr | 文件一变就触发命令 |
| 导航与终端 | hyperfine | 给命令做基准测试 |
| 导航与终端 | broot | 树形浏览加快速定位 |
| 系统观测 | htop | 进程和资源概览 |
| 系统观测 | btop | 更好看的资源面板 |
| 系统观测 | glances | 一屏看全 CPU、内存、磁盘、网络 |
| 系统观测 | procs | 比 ps 好读的进程列表 |
| 系统观测 | lsof | 查文件被谁占用、端口被谁监听 |
| 系统观测 | ss | 看套接字连接状态 |
| 系统观测 | ncdu | 交互式磁盘占用分析 |
| 系统观测 | dust | 一眼看出哪个目录最占地方 |
| 系统观测 | duf | 磁盘剩余空间汇总 |
| 系统观测 | strace | 跟踪进程系统调用,定位卡在哪 |
| 网络排查 | curl | 发请求、下文件、调接口 |
| 网络排查 | wget | 断点续传下载 |
| 网络排查 | httpie | 更好读的 HTTP 请求工具 |
| 网络排查 | dig | 域名解析排查 |
| 网络排查 | mtr | 链路质量持续观测 |
| 版本协作 | git | 版本控制本体 |
| 版本协作 | gh | 在终端里管仓库、PR、Issue |
| 版本协作 | lazygit | 交互式 git 操作面板 |
| 版本协作 | tig | 终端里翻提交历史 |
| 版本协作 | delta | 让 diff 变成高亮分栏 |
| 版本协作 | pre-commit | 提交前自动跑检查 |
| 版本协作 | just | 任务入口,替代零散脚本 |
| 版本协作 | act | 本地跑 CI 流程 |
| 容器与云原生 | docker | 容器本体 |
| 容器与云原生 | kubectl | 集群操作入口 |
| 容器与云原生 | helm | 清单模板化部署 |
| 容器与云原生 | k9s | 集群交互式面板 |
| 容器与云原生 | stern | 多 Pod 日志聚合查看 |
| 容器与云原生 | dive | 分析镜像分层体积 |
| 容器与云原生 | terraform | 基础设施声明式管理 |
| AI 编程 | codex cli | 终端里的编码助手 |
| AI 编程 | deepseek cli | 另一条模型接入路径 |
| AI 编程 | trae cli | 编辑器与终端联动 |
| AI 编程 | gemini cli companion | 编辑器侧的 CLI 配套 |
| AI 编程 | aider | 直接改仓库文件的助手 |
表格里加起来已经超过五十个,实际装的比这还多一些零散的。接下来挑重点讲,讲清楚每个工具我为什么用它,以及踩过什么坑。
2. 文本与文件处理:使用频率最高的一批
这一类是我每天调用次数最多的。写代码、看日志、改配置,本质上都是文本处理。所以这一层的工具替换收益最大,一个工具快一倍,一天累积下来就是几十分钟。
2.1 ripgrep、fd、bat 三件套为什么值得换掉老命令
rg替代grep -r,核心差异有三个。第一,它默认读取.gitignore,不会去翻node_modules和编译产物,这一条就能让搜索快十倍以上。第二,它用多线程并行遍历目录,磁盘再慢也能压满。第三,它默认开启高亮和行号,输出直接可读。我常用的写法是rg -n --hidden -g '!*.min.js' "关键字" src/,--hidden让它别漏掉点开头的目录,-g用来排除压缩产物。
fd替代find,最大的好处是语法短。找一个名字带 config 的 yaml:fd -e yaml config。按大小过滤:fd -S +10M。按修改时间过滤:fd --changed-within 2d。这些参数的写法比find的-size、-mtime直观太多。它同样默认尊重忽略规则,如果你想全盘搜,加-I或者-u。
bat替代cat,提供语法高亮、行号和分页。看一个长文件的时候差别特别明显。它还有一个很实用的用法,把行号当作参数给别的工具。比如我经常想看第 120 到 180 行,直接bat -r 120:180 file.go,不用去数。bat输出到管道时会自动退化成纯文本,不会把高亮控制符塞进下一级命令,这个设计很贴心。
注意:不要图省事把 alias 写成
alias grep=rg。很多脚本和构建工具内部依赖grep的原始行为,尤其是退出码和特定参数,覆盖之后容易出现莫名其妙的失败。想少打字就给rg单独设短别名,别动原命令。
2.2 jq 与 yq:把结构化数据当数据库查
jq我用了很多年,还是觉得它是命令行里最值回票价的工具之一。最基础的用法是格式化:jq . data.json。但真正省事的是查询。举个例子,一堆日志里要统计每种错误码出现次数:
jq -r '.error.code' app.log | sort | uniq -c | sort -rn这里的-r是去掉输出里的引号,不加的话后面管道处理会多出一层引号。再比如给字段补默认值并筛选:
jq -c '.[] | select(.status == "failed") | {id, msg: (.message // "unknown")}' result.json-c是紧凑输出,一行一条,方便再喂给别的工具。select负责过滤,//是默认值运算符。这几个组合起来,基本能覆盖日常九成的 JSON 处理需求。
yq是处理 YAML 的对应工具,改 K8s 清单或者 CI 配置时特别顺手。常见操作比如改镜像版本:yq -i '.spec.template.spec.containers[0].image = "app:v2"' deploy.yaml。-i表示原地写回,建议第一次先用不带-i的命令确认输出对了再写。也可以多份清单批量改:yq -i '.metadata.labels.env = "prod"' *.yaml。
2.3 fzf:一个把"选择"做成积木的工具
fzf本身不做任何业务,它只负责把标准输入的一堆行变成可搜索、可上下选、可回车的交互界面。但正因为这样,它能插进任何地方。装完之后会自动接管几个快捷键:Ctrl-R变成历史命令模糊搜索,Ctrl-T在当前目录里选文件并插入到命令行,Alt-C用来选目录并跳过去。这三个快捷键用熟了,敲命令的速度会有质的变化。
更进阶的用法是配 preview。比如我选文件的时候顺便看内容:
fd -t f | fzf --preview 'bat --color=always -n {}' --height 60% --border--preview里的{}就是当前高亮那一行。还可以把 git 分支、容器名、进程列表、提交历史都喂进去。说白了,凡是"从一堆东西里挑一个"的场景,都可以交给它。
顺手提一个相关工具sd,它是给"替换"这个动作做减法的。sd 'old' 'new' file就够了,不用记sed里那些转义规则。批量替换多个文件的写法是配fd:
fd -e md | xargs sd '旧词' '新词'2.4 这一层的实操心得与几个坑
第一个坑是编码。老项目的日志可能是 GBK 编码,rg搜中文会搜不到。可以加-E gbk指定编码,或者先iconv -f gbk -t utf-8转一遍。这个问题在 Windows 上尤其常见。
第二个坑是大文件。rg遇到一个几十 MB 的单行 JSON 会非常吃内存。可以加--max-columns 500限制单行输出长度,或者先用jq切出需要的字段再搜。
第三个坑是xargs的参数长度限制。文件特别多的时候,命令会报 "Argument list too long"。解决办法是用-n限制每次传几个参数,或者改用rg自带的-0加xargs -0处理带空格的文件名。带空格和换行的文件名是命令行里最经典的坑,凡是把文件名往管道里传,最好都用-0分隔。
第四个节约时间的技巧:善用entr和watch做自动化。entr的用法是它读标准输入的变更列表,文件一变就执行命令。比如fd -e go | entr -c go test ./...,改代码自动跑测试。写前端或者写脚本时特别省事,不用来回切窗口。
3. 目录跳转、终端复用与提示符配置
这一部分解决的是"人机交互"层的效率。工具再快,如果你每次都要手敲一长串路径、或者不小心关了窗口丢掉半天的会话,整体效率还是上不去。
3.1 zoxide 用"记忆"代替路径输入
zoxide的思路很简单:它记录你去过哪些目录,然后给每个目录算一个权重,按访问频率和时间衰减。用的时候就写关键词,比如我常去的一个服务目录叫billing-service,不管我在哪,敲z bil就直接跳过去。第一次用会觉得有点玄学,用两周之后基本告别cd ../../..。
它的权重算法里访问频率占大头,但最近的访问会加权,所以热点会自然浮现。有几个常用子命令值得记一下:z -l列出记录,z -i交互式挑选,如果想让某个目录永远排第一,用zoxide add 路径手动加权重。有人担心它泄露隐私,这个记录文件在你自己的家目录里,正常使用没有问题,介意的话可以定期清理。
和它同一类的还有fzf的Alt-C,两者不冲突。我的习惯是熟悉的关键词用z,不记得名字的时候用Alt-C模糊找。
3.2 tmux:会话不丢才算真正能干活
tmux的价值主要在三件事上。第一,远程连接的会话保持,网络一旦抖动,重连之后tmux attach一切照旧,正在跑的任务也不会被打断。第二是分屏,一个窗口里同时看日志、跑构建、改代码,不用来回切终端标签。第三是可以在里面跑长任务,然后断开去做别的事,回头再看结果。
配置上我改了两处。一是把前缀键从Ctrl-B改成Ctrl-A,因为前者离手指太远,用久了手腕疼。二是把窗口和分屏的快捷键都挂上,减少记忆负担。常用的几条:Ctrl-A c新建窗口,Ctrl-A ,重命名窗口,Ctrl-A %竖切,Ctrl-A "横切,Ctrl-A d断开,tmux attach -t 名字回来。
还有一个被低估的功能是日志留存。Ctrl-A :进去执行capture-pane -S -3000,可以把当前面板的回滚内容抓出来存文件。排查问题时,把现场日志留下来比截图靠谱得多。如果需要长时间记录,可以开pipe-pane把输出实时写到文件。
3.3 starship、direnv 与 tldr:把环境和提示符管起来
starship是一个跨 shell 的提示符生成器,一份配置在所有 shell 里通用。它最实用的地方是自动显示当前目录的 git 分支、改动状态、语言版本、命令执行耗时。命令耗时显示这条特别有用,超过一定秒数才会出现,我能马上知道刚才那步是不是卡住了。配置就是一个starship.toml,改完对所有终端生效。
direnv解决的是环境变量随目录切换的问题。在项目根目录放一个.envrc,里面写export API_BASE=http://localhost:8080,进入这个目录变量自动生效,离开自动失效。以前我每个项目都得写个env.sh手动 source,经常忘了导致连着测试环境跑本地代码。用了direnv之后这类事故基本消失了。第一次用.envrc需要执行direnv allow授权,这是它的安全设计。
tldr是"简化版 man 手册",只给你几个最常见的例子,不跟你讲参数历史。忘了某个命令怎么用,tldr tar比翻 man 快得多。我通常装两个:tldr查通用命令,cheat存自己攒的偏门用法,比如某个内部系统的固定调用方式。
3.4 一套可以照抄的最小配置
我的~/.zshrc里跟这一层相关的部分大概是这样的:
# 导航 eval "$(zoxide init zsh)" eval "$(starship init zsh)" eval "$(direnv hook zsh)" # fzf 绑定 source /usr/share/fzf/key-bindings.zsh # 别名 alias ll='eza -lah --git' alias cat='bat --style=plain' alias grep='rg --color=auto' alias top='btop' alias ports='ss -tulpn'最后这条ports我用了好几年,查哪个进程占了端口特别快。cat那条别名要小心,它会改变cat在交互式 shell 里的行为,脚本里不受影响,所以风险可控。但如果你有脚本在交互式环境下被调用,还是别改cat更稳妥。
4. 版本控制与发布链路
开发工作里有一大块时间花在"提交、审查、构建、发布"这条链路上。git本身已经很强,但它原生的一些输出对人不友好,这块有大量工具可以补。
4.1 git 与 gh 的分工
git管本地仓库,gh管远端平台。我平时不怎么开浏览器,建 PR、看 CI 状态、看 Issue 基本都在终端里完成。常用几条:gh pr create --fill用提交信息自动填 PR 标题和描述,gh pr checks看 CI 结果,gh run watch盯着构建跑完,gh issue list -a @me看分给我的工单。
gh还支持gh api直接调接口,遇到它没封装好的功能,用这个方法能兜底。比如批量给一批 PR 加标签,写个循环就行。这条通路的价值在于它把"平台操作"也变成了可脚本化的动作,重复性工作可以直接写成脚本,不用手点。
4.2 lazygit、tig 与 delta:让历史变得可读
lazygit是一个终端里的交互式 git 面板,左边看文件状态,中间看 diff,右边看分支和提交。它的核心价值在于把"暂存部分改动"这件事变得极其直观,按空格逐块选择,比git add -p一次次回答 y/n 快得多。解决冲突、挑拣提交、撤销操作也都在面板里完成。
tig是用来翻历史的,tig blame 文件和tig log我都常用。它的界面轻,响应快,看谁在什么时候改了哪一行特别直接。
delta是给 diff 做美化的,装上之后git diff会变成左右分栏加语法高亮。它不是纯装饰,高亮能让人更快定位到改动内容,尤其是配置文件里改了一个值的那种。配置很简单,在.gitconfig里加:
[core] pager = delta [interactive] diffFilter = delta --color-only [delta] side-by-side = true line-numbers = true注意:
delta在超大 diff 上会比较慢,因为它要做语法分析。碰到几千行的改动,临时用git --no-pager diff看原始输出更快。
4.3 pre-commit、just 与 act:把"本地能跑"变成承诺
pre-commit是一个提交前钩子管理工具。它的好处是配置写在 YAML 里,跟着仓库走,新同事 clone 下来执行一次安装,检查规则就统一了。我一般会挂上格式化、静态检查、敏感信息扫描这几类钩子。它只检查改动的文件,所以不会拖慢提交流程。别把所有重活都塞进去,测试套件那种几十秒的东西还是留在 CI 里跑。
just是任务入口工具。项目里总有那么一堆零散脚本:起服务、跑迁移、清缓存、打镜像。散在十几个文件里,新人根本不知道从哪开始。用justfile把它们收拢,每个任务写一行说明,直接just不带参数就能列出全部可用命令。这比维护一个 README 列表靠谱,因为它是可执行的,不会过期。
act能在本地跑 CI 流程。它模拟 CI 环境,把工作流文件在容器里执行一遍。我一般只用来验证工作流的语法和逻辑,不指望它百分百等价于真实环境,因为环境变量和缓存机制总有差异。但它能帮你在推代码之前发现"步骤名写错""路径不存在"这类低级错误,省掉一轮等待。
4.4 一条从改动到发布的最小链路
我把这条链路串一下,你可以照着改:写完代码先just fmt和just lint本地过一遍,然后git add -p分块暂存,git commit触发pre-commit钩子自动检查,gh pr create --fill建 PR,gh pr checks等 CI 结果,合并之后gh run watch盯着发布流程跑完。
需要人工介入的只有两处:写提交信息和在 CI 失败时判断原因。其余都是命令。这套流程我用了两年多,最大的收获不是省了多少时间,而是出错的地方变得可定位——每一步都有明确输出,不像手点的时候"我也忘了刚才点了什么"。
5. 系统观测、网络排查与容器操作
这一类工具平时存在感不强,但出事的时候全靠它们。我建议提前装好,别等到线上告警了再去想用什么命令。
5.1 资源观测:从 htop 到 dust
htop大家基本都用,我算是把它当作默认起点。btop的界面更现代,有图形化的 CPU 和网络曲线,直观一些。glances的特点是聚合,一屏里同时给 CPU、内存、磁盘、网络、进程排行,在只有一屏空间的远程机器上特别合适。
duf是磁盘空间汇总,一条命令列出所有挂载点的使用率和剩余量,比df -h的输出好读。dust是目录级别的占用排行,dust -d 2只看两层,立刻能看出是哪个目录吃掉了空间。ncdu提供交互式浏览,可以一层层点进去,还能直接删文件。三个工具配合起来,排查磁盘问题基本是分分钟的事。
5.2 网络排查:curl、httpie、dig、ss、lsof
curl是万能工具,但很多人只会curl url。几个我常用的参数值得记住:-i显示响应头,-v显示完整握手过程,-L跟随跳转,--resolve手动指定域名解析结果,用来验证某个后端节点是否有问题。还有-w可以自定义输出格式,把状态码和耗时打出来:
curl -o /dev/null -s -w 'code=%{http_code} dns=%{time_namelookup} total=%{time_total}\n' https://example.com/api/health这条命令在做接口健康检查的时候特别有用,可以写进循环里定时探活。
httpie是curl的易读版,发 JSON 请求时不用手写-H 'Content-Type: application/json' -d '...',直接http POST url key=value就行。它把语法简化了,但也因此不适合写复杂脚本,两者是互补关系。
dig用来确认解析是否符合预期,dig +short最常用。ss替代老旧的netstat,ss -tulpn能列出所有监听端口和对应进程。lsof -i :8080直接告诉你谁占了这个端口。这几个命令组合起来,能把"服务起不来"这类问题快速定位到具体环节。
5.3 容器与云原生:kubectl 之外还值得装什么
kubectl是基础,但它有一个明显问题:命令太长。我一般会在 shell 里配好补全,再加几个常用别名,比如k、kgp(get pods)、klf(logs -f)。别加太多,别名太多反而记不住。
k9s是一个集群的交互式面板,看到 Pod 状态、进去执行命令、看日志、改副本数,全在键盘上操作。它省掉的是"我要敲哪个子命令"的记忆负担。排查问题的时候,来回切换 Pod 看日志特别方便。
stern解决的是多 Pod 日志聚合。一个服务有十个副本,出问题的时候你不会想开十个窗口。stern 服务名 -n 命名空间直接把所有副本的日志混在一起输出,还能按标签过滤。这个工具我装了之后就离不开了。
dive用来分析镜像分层。它能列出每一层新增了哪些文件、占了多少空间,找出那些"不小心把构建缓存打进去了"的层。镜像瘦身的时候非常有用,有时候能省下几百 MB。
helm和terraform属于另一个层面的工具:前者把清单模板化,后者把基础设施声明化。它们的共同点是学习曲线陡,但一旦用起来,环境的一致性问题会少很多。我的建议是别一开始就追求全量迁移,先把一个新服务用起来,跑顺了再谈别的。
5.4 一个"磁盘满了"的完整排查过程
这套流程我走过很多次,写下来你可以直接套用。第一步,duf看是哪个挂载点满了。第二步,dust -d 2 目标目录,看是哪几个子目录占大头。第三步,进到具体的目录,ncdu交互式看,找出具体文件。第四步,如果是日志文件,先确认是否还在被写入,用lsof 文件名查。第五步,确认可以清理之后,用truncate -s 0 文件名清空而不是直接删,因为直接删掉正被进程持有的文件,空间不会立刻释放,得等进程重启。
最后这一步是个经典坑。很多人删了文件发现空间没回来,以为是系统有问题,其实就是进程还握着文件句柄。搞清楚这一点,能省掉不少排查时间。
6. AI 编程 CLI:这一批才是最近真正离不开的
最近这半年,我终端里新增的工具几乎全是这一类。它们的共同点是:把模型的读写能力接到本地仓库和命令上,让"让 AI 帮我处理这件事"变成一个命令,而不是切窗口复制粘贴。
6.1 codex cli 装不上、跑不起来怎么排查
先说安装。这类工具通常通过包管理器分发,用全局安装的方式装到系统里,装完在终端里能直接调用。这个过程看起来简单,但踩坑率其实挺高,我自己和同事都遇到过。
最常见的报错是提示找不到对应的可执行文件,也就是类似 "unable to locate the codex cli binary" 这种信息。这个报错的含义很明确:调用方知道要执行哪个命令,但在系统的可执行文件搜索路径里找不到它。按下面这个顺序排查,基本能解决:
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 安装命令报权限错误 | 全局目录需要写权限 | 用包管理器调整权限,别直接改系统目录权限 |
| 装完命令不存在 | 全局 bin 目录不在 PATH 里 | 查询包管理器全局 bin 路径,加入 PATH 并重载配置 |
| 重装后找不到 | 版本管理工具切换了运行时版本 | 确认当前运行时版本下是否真的装了 |
| 偶发找不到 | shell 命令哈希缓存过期 | 执行一次哈希刷新命令 |
| 报运行时版本不匹配 | 该工具要求较新的运行环境 | 检查版本号,按官方说明切换 |
排查顺序建议从 PATH 开始,因为九成的问题都在这。你可以先执行which 命令名看能不能找到,找不到就说明 PATH 里没有它的目录。再用包管理器自己的查询命令确认它到底装在哪,两个结果一对,问题就清楚了。
另外提醒一点:如果你用版本管理工具切换运行时版本,全局安装的包是分版本存放的。切到一个新版本之后,之前装的工具会全部"消失",需要重新装一遍。这个行为容易让人困惑,但它是设计如此。
6.2 日常用法和省成本的几个技巧
这类工具的基本用法都差不多:进到项目目录,启动会话,然后用自然语言描述你要做什么。它会自己读文件、改代码、跑命令。用下来我总结了几条经验。
第一是控制上下文范围。启动之前先明确告诉它只看某个目录,别让它扫整个仓库。一个几万文件的项目,全量扫描既慢又烧钱。第二是把常用指令写成项目的说明文件放在仓库根目录,它会自动读取,相当于给助手一份项目背景,省掉每次重复解释。第三是让它先输出方案再动手,尤其是改动涉及多个文件的时候,先看它打算怎么改,确认没问题再执行。
第四点关于成本:这类工具一般按输入输出量计费,长上下文和大文件是主要开销来源。我的做法是排查类任务用轻量方式(比如直接丢给它一段日志),重构类任务才开完整模式。另外别让它反复读同一个文件,可以在对话里直接贴关键片段。
6.3 几条不同的接入路径怎么选
现在终端里的编码助手有好几条路径,定位差别挺大,我按自己的使用感受列一下:
| 工具 | 主要形态 | 适合的场景 |
|---|---|---|
| codex cli | 终端交互式会话 | 在仓库里做多文件改动、跑命令 |
| deepseek cli | 终端调用模型能力 | 需要按自己的方式接入模型时 |
| trae cli | 编辑器与终端联动 | 边写边让助手看当前文件 |
| gemini cli companion | 编辑器侧配套扩展 | 在编辑器里直接调起命令行助手 |
| aider | 面向仓库的自动改码 | 批量重构、按文件粒度提交 |
选择的逻辑其实很简单:如果你的主要工作是在终端里跑命令和改代码,就用终端优先的那类;如果你大部分时间在编辑器里,就选和编辑器联动的那类。不需要全都装,选一条顺手的,把常用指令和项目说明配好,收益就出来了。
至于把 CLI 的输出接到团队协作工具里,思路是通用的:多数协作平台都提供消息接口,你只要把结果拼成 JSON,用curl发一个 POST 请求就行。比如构建完成后自动推一条结果到群里:
curl -s -X POST "$CHAT_WEBHOOK" \ -H 'Content-Type: application/json' \ -d "{\"msg_type\":\"text\",\"content\":{\"text\":\"构建完成: $STATUS, 分支 $BRANCH\"}}"关键点在于那个 webhook 地址不要硬编码在脚本里,放在环境变量或者direnv管理的.envrc里。硬编码的密钥进了仓库,清理起来非常麻烦,得逐个提交改历史。这是我在项目里反复强调的一条纪律。
6.4 用这类工具的三条红线
第一条是别把密钥、客户数据、私有配置贴进对话。哪怕是排查问题,也要先脱敏。我一般会把日志里的地址、账号、token 用占位符替换掉再给。
第二条是别让助手直接对生产环境执行命令。它可以生成命令给你,但执行这一步必须由人来做。自动化脚本里也别开这个口子。
第三条是审查它的每一处改动。这类工具的错误往往很隐蔽,比如把一个边界判断写反了,测试刚好没覆盖到。改动之后跑一遍完整测试,别嫌麻烦。
7. 常见问题与排查技巧实录
命令行工具的坑有很强的共性,很多问题第一次遇到要查半天,知道了之后就是一句话的事。这一节把高频问题集中整理一下。
7.1 command not found 的四类成因
这个报错几乎是所有人都会遇到的第一个问题。它背后的原因只有四类。第一类是确实没装,或者装到了别的地方。第二类是装了但目录不在 PATH 里,这是最常见的一类。第三类是用版本管理工具切换了运行环境,全局包换了一套。第四类是 shell 的命令缓存过期了,这时执行一次哈希刷新或者重开终端就能解决。
排查的第一步永远是which 命令名和echo $PATH。把这两个输出对照看,问题基本就定位了。如果是第二类,就在 shell 配置里加一行导出语句,注意路径要写全局 bin 目录而不是包自己的目录。改完记得重新加载配置,或者在当前会话里手动执行一次导出。
注意:PATH 的顺序会影响命令解析结果。如果你在某个目录下有个同名脚本,它的目录排在 PATH 前面,执行的就是它而不是你预期的工具。排查诡异行为的时候,先用
type -a 命令名看看一共有几个同名命令。
7.2 管道与 xargs 的坑
第一个坑是上游命令提前退出导致下游收到信号。典型场景是命令 | head,head读够行数就退出,上游写入时收到管道中断信号。这在大多数情况下是无害的,但如果上游是关键步骤,退出码会变成非零,导致 CI 判定失败。处理办法是用set -o pipefail时留意这种情况,或者把head换成awk之类的完整读取方式。
第二个坑是参数过长。"Argument list too long" 报错说明一次性传的参数超出了系统限制。解决方式是xargs -n 20,每次传二十个。如果不确定,用-n配合-P还能并行处理,速度会更快。
第三个坑是文件名里的空格和特殊字符。凡是可能带空格的文件名,一律用空字符分隔:上游产出的工具加空字符输出参数,xargs用对应的方式接收空字符分隔。这套写法要养成习惯,因为它在本地测试时往往看不出来,一上生产就出问题。
第四个坑是xargs默认会把引号当特殊字符处理,导致命令拼接结果和你预期不一致。如果担心这个问题,可以用-0或者把命令换成脚本文件调用,减少引用层级。
7.3 换行符、编码与终端渲染
跨平台协作最容易踩的就是换行符。有的系统用回车加换行,有的只用换行,提交到仓库之后整个文件显示为全量修改。解决办法是在仓库加一个属性配置,把文本文件统一成一种换行符,同时把二进制文件排除在外。这类配置一次搞定,能省掉无数次"为什么 diff 显示整个文件都变了"的困惑。
编码问题主要出现在处理中文日志和 CSV 上。判断方式是看文件开头的字节序列有没有编码标记。没有标记的老文件,得手动指定编码。转换的时候用通用编码转换工具,注意先备份原文件,因为转换方向搞反了会得到一堆乱码。
终端渲染问题一般是字符宽度导致的表格错位。中文字符占两个显示宽度,西文占一个,如果工具按字符数算宽度,表格就会歪。这类问题没有万能解法,能改配置就改配置,改不了就换成用制表符分隔的输出来看。
7.4 高频问题速查表
| 问题 | 现象 | 处理方向 |
|---|---|---|
| 命令找不到 | command not found | 查 which 与 PATH,确认安装位置 |
| 装完要重开终端 | 当前会话无效 | 重新加载 shell 配置 |
| 搜索没结果 | 中文内容搜不到 | 指定文件编码 |
| 管道报错 | 上游退出码非零 | 检查上游是否被中断信号影响 |
| 参数过长 | Argument list too long | 分批传参或并行处理 |
| 空间没释放 | 删除后磁盘仍满 | 检查文件是否被进程占用 |
| diff 全量变化 | 换行符不一致 | 统一仓库文本换行配置 |
| 表格错位 | 中英文混排 | 改用分隔符输出或调整宽度设置 |
| 命令行为诡异 | 同名命令被覆盖 | 用 type -a 查看解析顺序 |
| 全局工具消失 | 切换运行时后找不到 | 在新版本下重新安装 |
7.5 关于工具数量的一个提醒
我见过不少人装了上百个命令行工具,结果常用的只有五六个。工具的边际收益是递减的,第二个文件搜索工具带给你的提升,远小于第一个。与其追求清单长度,不如把已经装的工具用透。
我自己判断一个工具是否值得留下的方法很朴素:装着它过两周,如果这两周里我一次都没主动调用过,就卸掉。如果调用次数超过十次,就去看它的文档,把高级用法学一学。留下来的工具,我都会在cheat里记几条自己总结的用法,下次忘了直接查。这个小习惯让我的工具链一直保持在二十个左右的"活跃"状态,剩下的都是备着以防万一的。
最后分享一个小技巧:把所有工具的安装命令集中在一个脚本里,按类别分段,加上注释说明每个是干什么的。新机器到手跑一遍,十分钟恢复完整环境。这个脚本我每年会精简一次,删掉不再用的,加上新发现的。它比任何工具清单文章都更有价值,因为那是完全为你自己的工作流量身定做的。