Unix 常用命令
Unix 常用命令全景指南
本文系统梳理 Unix/Linux 环境下的高频命令,从命令行语法基础到生产环境实战,覆盖文件操作、文本处理、系统监控、开发工具四大场景。
目录
命令行基础
命令行参数的三元素
Unix 命令行由三种基本元素组成:选项、位置参数和子命令。
基本结构
1 | |
选项(Options)
以 - 或 -- 开头的参数,用于修改命令行为:
| 类型 | 格式 | 示例 |
|---|---|---|
| 短选项 | - + 单个字母 |
-a, -v, -h |
| 长选项 | -- + 单词 |
--help, --verbose |
| 带参数的选项 | -n value 或 --name=value |
-n namespace, --port=8080 |
短选项支持合并书写:ls -la 等价于 ls -l -a。
位置参数(Positional Arguments)
不带连字符的参数,其含义由出现的位置决定:
1 | |
子命令(Subcommands)
特殊的命令块,通常有独立的帮助文档:
1 | |
快速识别子命令的方法:
- 查看独立帮助:
command subcommand --help - 使用 Tab 补全:输入命令后按
Tab键 - 观察命令结构:子命令通常在全局选项之后
🔑 模式提炼:参数解析通用规则
核心公式:{command} [{global_options}] {subcommand} [{local_options}] {args...}
| 场景 | 全局选项 | 子命令 | 本地选项 | 示例 |
|---|---|---|---|---|
| Docker 容器管理 | -H tcp://host:2375 |
run |
-p 80:8080 |
docker -H host run -p 80:8080 nginx |
| Kubectl 集群操作 | --namespace=prod |
get pods |
-o wide |
kubectl --namespace=prod get pods -o wide |
| Git 版本控制 | -C /path/to/repo |
log |
--oneline -10 |
git -C /repo log --oneline -10 |
核心洞察:所有遵循 POSIX 规范的命令都共享相同的参数解析逻辑——先处理全局选项,再识别子命令,最后解析子命令特有的选项和参数。
文件与目录操作
浏览与定位
1 | |
文件与目录管理
1 | |
查找与统计
1 | |
tar 压缩与解压
1 | |
🔑 模式提炼:批量操作的安全范式
核心公式:find {搜索范围} {过滤条件} | xargs {处理命令}
| 场景 | 搜索范围 | 过滤条件 | 处理命令 |
|---|---|---|---|
| 批量删除旧日志 | /var/log |
-name '*.log' -mtime +30 |
rm -f |
| 批量修改文件权限 | . |
-type f -name '*.sh' |
chmod +x |
| 批量文本替换 | ./src |
-name '*.java' |
sed -i 's/foo/bar/g' |
核心洞察:find + xargs 是 Unix 哲学的典型体现——每个工具专注单一职责,通过管道组合完成复杂任务。相比 find -exec,xargs 性能更优(减少进程创建开销),且支持并行处理(-P 选项)。
安全注意事项:
- 执行破坏性操作前先用
-print0 | xargs -0 echo预览 - 文件名包含空格时必须使用
-print0+xargs -0
文本处理三剑客
grep:模式匹配
1 | |
awk:列数据处理
1 | |
sed:流编辑器
1 | |
🔑 模式提炼:文本处理的组合策略
核心洞察:三剑客的组合遵循"过滤 → 提取 → 转换"的数据流模型。
| 阶段 | 工具 | 职责 | 口诀 |
|---|---|---|---|
| 过滤 | grep |
缩小数据范围 | “先 grep 降噪” |
| 提取 | awk |
切分字段、聚合计算 | “awk 取列求和” |
| 转换 | sed |
就地修改、格式转换 | “sed 就地替换” |
经典组合示例:
1 | |
系统与资源监控
磁盘空间分析
1 | |
三种查空间方式的取舍:
| 命令 | 统计对象 | 适用场景 | 局限 |
|---|---|---|---|
du -ah ./ | sort -rh |
目录 + 文件(含目录累计) | 想知道哪个目录整体最占地方 | 要遍历统计,目录深时慢;只看当前目录树 |
find . -size +100M -ls |
单个文件 | 快速列出当前目录下的大文件 | 不排序、格式杂乱、范围限于 . |
find / ... -printf | sort -rn |
单个文件(全盘) | 磁盘告警时全盘定位最大的几个文件 | 需 root 才能看全,不做目录聚合 |
进程与性能监控
1 | |
🔑 模式提炼:性能瓶颈排查路径
核心公式:宏观 overview → 定向钻取 → 关联验证
| 层级 | 命令 | 关注指标 | 异常阈值参考 |
|---|---|---|---|
| 系统整体 | uptime / top |
load average | > CPU 核心数 × 2 |
| 磁盘 I/O | iostat -xz 1 |
%util, await | %util > 80% |
| 内存 | free -h |
available | < 20% 总内存 |
| 网络 | ss -s |
TCP 连接状态 | TIME_WAIT 过多 |
| 进程级 | pidstat -u 1 |
%CPU/%MEM | 单进程 CPU > 100% |
开发环境工具链
Homebrew(macOS)
1 | |
SDKMAN(多版本 SDK 管理器)
1 | |
🔑 模式提炼:版本管理的隔离策略
核心洞察:开发环境的版本冲突本质是命名空间隔离问题。两种主流方案:
| 方案 | 工具代表 | 隔离粒度 | 适用场景 |
|---|---|---|---|
| 全局切换 | SDKMAN、pyenv、nvm | 用户级 | 个人开发机,频繁切换版本 |
| 项目锁定 | Maven Wrapper、Gradle Wrapper、npx | 项目级 | 团队协作,确保构建一致性 |
推荐实践:团队项目优先使用 Wrapper 机制,CI/CD 和个人开发配合 SDKMAN。
磁盘告警定位实战
场景还原:一台跑在容器里的服务器触发「磁盘利用率 95%,最近 5 分钟连续大于 95%」告警。要解决它,得先回答两个问题——哪个文件在吃盘,以及它落在哪块设备上。这一节把完整排查思路走一遍,并把过程中踩到的两个同类陷阱当反面教材记下来,因为陷阱本身比结论更值钱。
排查心法:df → 定位设备 → du/find 下钻 → lsof 兜底
一句话记住顺序:
先用 df 看哪块盘满、它对应什么设备;再用 du/find 一层层往下钻,定位到目录和具体文件;如果 df 说满了、du/find 却怎么都找不到,最后用 lsof 揪出「已删除但仍被进程占用」的隐身文件。
这套顺序背后是一个通用原则:df 报的是「块设备层」的真实占用,du/find 走的是「文件系统目录树」。两者视角不同,绝大多数「找不到」的诡异现象,都源于把这两个层面混为一谈。
第一步:df 看哪块盘满,并认清设备与挂载点
1 | |
一台容器机的典型输出(关键几行):
1 | |
读这张表要抓三列:
- Filesystem:这块空间背后的设备。
overlay是容器的联合文件系统,/dev/nvmeXnY是实打实的块设备分区,tmpfs是内存盘(不占磁盘,别去清它)。 - Use%:利用率。哪行接近 100% 就盯哪行。
- Mounted on:这块设备挂在文件系统的哪个路径上。容器环境最容易在这里翻车——同一台机器上会有一堆
/dev/termination-log、/etc/route.tmpl这种「名字看着像文件、其实是独立挂载点」的 bind mount,各自是独立的盘。
容器环境的核心认知:根 / 只是 overlay,真正的数据往往分散在一堆旁挂的子挂载盘上。这个认知直接决定了后面 du/find 该怎么用。
定位设备:给一个路径,反查它落在哪块盘
「定位设备」的本质是一个反向映射:已知一个文件/目录路径,问它到底写在哪块物理设备上。三个工具,从快到细:
1 | |
| 你的问题 | 命令 | 给你什么 |
|---|---|---|
| 这个路径写在哪块盘? | df -Th <路径> |
该路径对应的设备名 + 挂载点 |
| 挂载关系和挂载参数? | findmnt -T <路径> |
目标/设备/类型/选项,一行齐全 |
| 整机有几块盘、怎么分区挂载? | lsblk -f |
物理设备的完整拓扑树 |
关键点:df 和 findmnt 都能直接接一个路径参数,帮你把「文件」翻译成「设备」。这是排查满盘时最容易被忽略、却最省事的一步——很多人上来就 find /,其实先 df <可疑目录> 一句话就知道该往哪块盘使劲。
第二步:du 往下钻定位目录——但当心 -x 陷阱
确定了满的那块盘,就顺着它的挂载点往下钻,找最肥的目录:
1 | |
这里踩了本次排查的第一个坑。 一开始为了「只统计当前这块盘」,习惯性加了 -x:
1 | |
-x 的语义是「不要跨越文件系统边界」,只统计当前这一个文件系统。可容器机的数据全在旁挂的子挂载盘上,-x 到挂载点就停住,把大头全跳过了,于是算出个荒谬的 27M。去掉 -x 立刻真相大白:
1 | |
1 | |
顺带暴露了 du -ah 的一个小毛病:前 5 行 /→/home→/home/admin→/home/admin/logs→tddl 全是同一个大文件的父目录逐层累加,属于「祖先链噪音」。目标只有一个时无所谓,但盘上若有好几个分散的大文件,这种噪音会把第二、第三名挤出 head。所以想干净地揪「文件」,下一步用 find 更利落。
第三步:find -size 直接揪大文件(无祖先链噪音)
1 | |
1 | |
这条命令是磁盘告警时定位大文件的首选,逐条拆解它为什么这么写:
- 不加
-xdev:这是本次踩的第二个坑,和du -x同源。-xdev也是「不跨文件系统」,一旦加上,子挂载盘里的 24G 日志同样会被跳过。在容器机上,凡是带「只看当前盘」语义的开关(du -x、find -xdev)都是帮倒忙,一律去掉。 -prune跳过/proc /sys /dev /run这些伪文件系统,避免误报和满屏报错。-type f -size +100M只要大于 100M 的普通文件,先粗筛降噪。-printf '%s\t%p\n'先输出原始字节数,好让sort -rn精确排序(直接输出人类可读单位会导致1.5G排在900M后面这种错乱)。- 最后一步才用
numfmt把字节转成 GB/MB,兼顾排序精度和可读性。
一个反直觉的坑:/var/log/lastlog 常年显示几个 G,但它是典型的稀疏文件(sparse file)——find/ls 报的是「表观大小」,实际只占几十 KB。想看真实占用得用 du -h /var/log/lastlog(会显示很小)。删它没意义,还可能出问题。
第四步:df 说满了、却怎么都找不到 → 删除未释放的文件
这是最能把人逼疯、也最能体现「df 与 du 视角差异」的场景:df 报盘满,du -ah 和 find 却把整块盘翻烂都凑不出那么多。答案几乎总是——某个文件被 rm 删掉了,但仍有进程攥着它的文件描述符(fd)在写。目录项已经没了(所以 find/du 看不见),可磁盘块还没释放(所以 df 照样算它)。日志轮转时最常见:轮转脚本删了旧日志,但 JVM 还开着那个 fd。
1 | |
找到后不要盲目 kill 进程,让应用重新打开日志(reload 或重启该进程)即可,磁盘块会立刻释放。
符号链接的坑:find 默认不跟随
排查中还容易被软链带偏。比如日志目录里常有这种软链:
1 | |
find 默认不跟随符号链接——遇到软链只把它当一个 link 列出来,不会踩进去遍历。如果目标文件藏在软链后面,直接 find / 会漏。两种解法:
1 | |
🔑 模式提炼:磁盘定位决策树 + 「只看当前盘」陷阱
核心公式:df 定位设备 → du/find 下钻文件 → lsof 兜底隐身文件
| 你的目标 | 最佳命令 | 为什么 |
|---|---|---|
| 哪块盘满了、是什么设备 | df -Th |
块设备层真实占用,认清挂载拓扑 |
| 某路径落在哪块盘 | df -Th <路径> / findmnt -T <路径> |
直接把文件反查成设备 |
| 哪个目录最占地方 | du -h <挂载点>(不加 -x) |
顺挂载点下钻,去掉 -a 减噪 |
| 最大的几个文件 | find / … -size +100M(不加 -xdev) |
逐文件、无祖先链噪音、跨挂载 |
| df 满了却找不到 | lsof +L1 |
揪出删了没释放的隐身文件 |
| 交互式清盘(有则首选) | ncdu -x <挂载点> |
方向键逐层进出、实时排序、按 d 删 |
核心洞察一:容器机的数据散落在旁挂的子挂载盘上,凡是带「只看当前盘」语义的开关——du 的 -x、find 的 -xdev——在这里都会让你漏掉大头。定位满盘时一律不加。(反过来,如果你明确只想统计单块盘、排除挂载进来的其他盘,才用 -x/-xdev。)
核心洞察二:df(块设备视角)和 du/find(目录树视角)的差异,是一切「盘满却找不到文件」谜题的根源。记住 df 会算上「已删除但被占用」的块,而 du/find 不会——这个缝隙正是 lsof +L1 要填的。
一行速记(存下来,下次磁盘告警直接用):
1 | |
唯一兜不住的情况就是「删了没释放」,那时才补一句 lsof +L1 2>/dev/null | sort -k7 -rn | head。
别忘了往上追一层:磁盘满往往是应用层的表象
清掉那两个 tddl 慢查询日志,盘会立刻从 87% 掉回 20% 出头。但清盘只是止血。回到这个真实案例:tddl-slow.log 一天堆出 37G,根因是应用层引入了一条「大行慢 SQL」——某张表的写入携带了十几 MB 的 JSON 大字段(把每一步的完整轨迹都塞进一个 mediumtext 列),既拖慢了 SQL、又把全量 SQL + 参数明文刷进慢查询日志,~2 条/分钟 就能撑爆一块 59G 的盘。
这就引出一个通用排查纪律:磁盘/日志类告警,定位到文件只是第一步,一定要再往上追一层「谁在往这里写、为什么写这么多」。否则清完还会涨回来。把「一个个满盘事件」抽象成「一类『应用日志失控』问题」,才是运维值守里真正省时间的思维方式。
磁盘扩容实战
适用于云服务器(阿里云/腾讯云/AWS 等)的场景:已完成云控制台扩容,但操作系统内未生效。
完整操作流程
1 | |
关键点说明
| 步骤 | 命令 | 作用域 | 风险等级 |
|---|---|---|---|
| 分区扩容 | growpart |
分区表 | ⚠️ 中(建议先备份) |
| 文件系统扩容 | resize2fs/xfs_growfs |
文件系统元数据 | ⚠️ 中 |
| 云盘扩容 | 控制台操作 | 底层存储 | 低(可随时扩容) |
核心原则:云盘扩容 → 分区扩容 → 文件系统扩容,三步缺一不可。resize2fs 只扩展文件系统到分区边界,若分区未扩容则不会生效。
速查表
常用命令索引
| 需求 | 命令 | 关键选项 |
|---|---|---|
| 查看磁盘 | df -Th |
-T 显示类型,-h 人类可读 |
| 某路径在哪块盘 | df -Th <路径> / findmnt -T <路径> |
把文件反查成设备 + 挂载点 |
| 查看设备拓扑 | lsblk -f |
设备 → 分区 → 挂载点的树 |
| 查看目录大小 | du -sh |
-s 汇总,-h 人类可读 |
| 全盘找大文件 | find / -type f -size +100M -printf |
配 sort -rn + numfmt,-prune 跳过伪文件系统,容器机别加 -xdev |
| 盘满却找不到文件 | lsof +L1 |
揪出「已删除但被进程占用」的隐身文件 |
| 压缩目录 | tar -zcvf |
-z gzip, -c 创建, -v 详细, -f 文件 |
| 解压 | tar -zxvf |
-x 解压, -C 指定目录 |
| 查找文件 | find |
-name, -type, -mtime, -size |
| 文本搜索 | grep |
-i 忽略大小写, -v 反向, -n 行号 |
| 列处理 | awk |
-F 分隔符, {print $N} 打印第N列 |
| 流编辑 | sed |
-i 原地修改, s/old/new/g 替换 |
危险操作 checklist
执行以下操作前请二次确认:
- [ ]
rm -rf前确认路径是否正确(尤其避免rm -rf /) - [ ]
>重定向会覆盖文件,意图追加请用>> - [ ]
find ... -delete和find ... | xargs rm效果相同,都不可逆 - [ ]
sed -i直接修改文件,重要文件先备份
进一步阅读
- Linux Command Line - 完整的命令行教程
- The Art of Command Line - 进阶技巧合集
- explainshell.com - 可视化解析命令

