Linux 管道命令使用笔记一、管道是什么管道pipe是 Linux 中一种强大的 IPC进程间通信机制使用竖线符号|表示。它将前一个命令的标准输出stdout直接连接到后一个命令的标准输入stdin使数据可以在多个命令之间流动而无需创建临时文件。管道是 Unix 哲学每个程序只做好一件事的核心支撑——通过管道将简单工具组合起来可以完成复杂的数据处理任务。二、基本语法与原理2.1 基本语法command1|command2|command3command1的 stdout →command2的 stdin →command3的 stdin。2.2 管道的底层原理管道在内核中维护一个环形缓冲区通常为 64KB由PIPE_BUF定义。写入端将数据放入缓冲区读取端从中取出数据。管道是单向的、半双工的通信通道。关键特性管道两端的命令是并发执行的而非串行如果管道缓冲区满了写入命令会被阻塞如果管道为空且写入端已关闭读取命令会收到 EOF管道中的命令运行在独立的子进程中子 shell2.3 管道的退出状态默认情况下管道的退出状态是最后一个命令的退出状态。使用$?查看false|trueecho$?# 输出 0true 的退出状态Bash 提供了pipefail选项让管道中任何命令失败时整个管道都返回失败set-opipefail# 启用seto pipefail# 禁用也可以使用PIPESTATUS数组获取管道中每个命令的退出状态command1|command2|command3echo${PIPESTATUS[]}# 输出各命令的退出码三、常用管道组合3.1 grep — 文本过滤# 在命令输出中搜索关键字psaux|grepnginxdmesg|grep-ierrorls-la|grep^d# 只列出目录cat/etc/passwd|grep/bin/bash# 查找使用 bash 的用户history|grepdocker# 搜索历史命令3.2 sort — 排序du-sh*|sort-h# 按人类可读的大小排序psaux|sort-k3-n-r# 按 CPU 使用率降序排序catwords.txt|sort|uniq# 排序后去重ls-la|sort-k5-n# 按文件大小第5列数字排序3.3 uniq — 去重# uniq 只能去除相邻的重复行通常与 sort 配合使用sortdata.txt|uniq# 去重sortdata.txt|uniq-c# 去重并统计出现次数sortdata.txt|uniq-d# 只显示重复的行sortdata.txt|uniq-u# 只显示唯一的行3.4 wc — 统计ls-1|wc-l# 统计文件数量psaux|wc-l# 统计进程数量catfile.txt|wc-c# 统计字节数catfile.txt|wc-w# 统计单词数find.-name*.go|wc-l# 统计 Go 文件数量3.5 head / tail — 取头部/尾部psaux|head-5# 前 5 行psaux|tail-5# 后 5 行psaux|tail-n2# 从第 2 行开始跳过表头dmesg|tail-20|grep-ierror# 查看最近的错误日志3.6 cut — 列提取cat/etc/passwd|cut-d: -f1,7# 提取用户名和 shellls-la|tr-s |cut-d -f5-9# 提取文件大小和名称ipaddr|grepinet |cut-d -f6# 提取 IP 地址3.7 awk — 强大的文本处理psaux|awk{print $2, $11}# 打印 PID 和命令df-h|awk$5 80 {print $0}# 找出磁盘使用率超过 80% 的分区psaux|awk{sum$3} END {print sum}# 计算 CPU 总使用率dockerps|awkNR1 {print $NF}# 提取容器名称跳过表头3.8 sed — 流编辑器ls-la|seds/^/ /# 每行前面加两个空格psaux|sed-n2,5p# 打印第 2 到 5 行catconfig.ini|seds/ / /g# 替换文本catfile.txt|sed/^$/d# 删除空行3.9 tr — 字符转换echoHello World|tr[:lower:][:upper:]# 转大写catfile.csv|tr,\t# 逗号转制表符catfile.txt|tr-s\n# 压缩空行catfile.txt|tr-d\r# 删除 Windows 换行符3.10 xargs — 将标准输入转为命令行参数某些命令如kill、rm、mv不接受标准输入作为参数xargs可以解决这个问题# 查找并删除所有 .tmp 文件find.-name*.tmp|xargsrm# 查找并杀掉进程psaux|greppython|awk{print $2}|xargskill-9# 批量创建目录echodir1 dir2 dir3|xargsmkdir# 使用 -I 自定义占位符更安全find.-name*.log|xargs-I{}mv{}/tmp/# 使用 -n 限制每次传递的参数数量echo{1..100}|xargs-n10echo# 与 -P 配合并行执行caturls.txt|xargs-P4-I{}curl-O{}注意文件名包含空格时使用find ... -print0 | xargs -0来正确处理。3.11 tee — 分流输出tee从标准输入读取数据同时写入标准输出和一个或多个文件——就像水管的三通接头# 同时输出到屏幕和文件command|teeoutput.txt# 追加到文件command|tee-aoutput.txt# 同时写入多个文件command|teefile1.txt file2.txt# 管道中间插入 tee 来调试command1|teedebug.log|command2|command3四、高级管道技巧4.1 命名管道FIFO匿名管道|只能在有亲缘关系的进程间通信。命名管道FIFO允许任意两个进程通信# 创建命名管道mkfifomypipe# 终端 1写入数据echoHello from another terminalmypipe# 终端 2读取数据catmypipe实用场景# 实时处理日志流mkfifo/tmp/logpipetail-f/var/log/nginx/access.log/tmp/logpipegrep404/tmp/logpipe|cut-d -f14.2 进程替换Process Substitution使用(command)或(command)可以让命令像文件一样被引用# 比较两个命令的输出差异diff(lsdir1)(lsdir2)# 比较排序后的文件comm(sortfile1.txt)(sortfile2.txt)# 合并多个命令的输出paste(cut-d:-f1/etc/passwd)(cut-d:-f7/etc/passwd)# 将输出发送到进程替换echodata(gzipoutput.gz)( )实际上是创建了一个命名管道并传递文件描述符给命令。4.3 多重管道与子 shell# 将管道输出赋值给变量total_lines$(catfile.txt|wc-l)echo文件有$total_lines行# 使用子 shell 组合多个命令(cat header.txt;catbody.txt)|grepkeyword# 将标准错误也导入管道bash 中command21|greperror# 只管道传递标准错误command21/dev/null|greperror4.4 条件管道# 在管道中使用 if 语句cat/etc/passwd|whileIFS:read-ruser _ uid _ _ home shell;doif[$uid-ge1000][$uid-lt60000];thenecho普通用户:$user(UID$uid, 家目录$home)fidone# 使用 awk 进行条件过滤df-h|awkNR1 || $50 80# 保留表头 高使用率行4.5 管道与循环# 注意管道中的循环运行在子 shell 中对变量的修改不会影响外部counter0seq15|whilereadn;docounter$((counter1))# 这在子 shell 中doneechocounter$counter# 输出 0而非 5# 解决方案 1使用进程替换whilereadn;docounter$((counter1))done(seq15)echocounter$counter# 输出 5# 解决方案 2使用 here-stringwhilereadn;docounter$((counter1))done$(seq15)五、实用范例合集5.1 系统运维# 查找占用 CPU 最高的 5 个进程psaux--sort-%cpu|head-6# 查找大目录du-sh/*2/dev/null|sort-h|tail-10# 查看当前连接数最多的 IPnetstat-ant|awk{print $5}|cut-d:-f1|sort|uniq-c|sort-rn|head-10# 查找最近修改的文件find.-typef-printf%T %p\n|sort-rn|head-10|cut-d -f2-# 查看各文件系统使用情况df-h|grep-v^tmpfs\|^devtmpfs5.2 日志分析# 统计 HTTP 状态码分布cataccess.log|awk{print $9}|sort|uniq-c|sort-rn# 查找 404 最多的 URLgrep 404 access.log|awk{print $7}|sort|uniq-c|sort-rn|head-10# 统计每小时请求量cataccess.log|awk{print $4}|cut-d:-f2|sort|uniq-c|sort-rn# 提取慢请求响应时间 1 秒awk$NF 1.0access.log|tail-205.3 数据转换# CSV 转 JSON简单版catdata.csv|awk-F,NR1{for(i1;iNF;i)h[i]$i;next} {printf {; for(i1;iNF;i) printf \%s\:\%s\%s,h[i],$i,(iNF?:,); print }}# 进制转换管道echoFF|tr[:lower:][:upper:]|xargs-I{}bash-cecho obase10; ibase16; {} | bc# URL 编码/解码echohello world|python3-cimport sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))5.4 开发相关# 统计项目代码行数排除空行和注释find.-name*.go|xargscat|grep-v^$|grep-v^\s*//|wc-l# 列出方法定义grep-rn^func --include*.go.|awk-F:{print $1:$2 $3}# 按作者统计 Git 提交gitlog--format%an|sort|uniq-c|sort-rn# 查找 Git 提交信息中的关键词gitlog--oneline|grep-ifix\|bug\|hotfix5.5 网络相关# 检测端口是否开放echoquit|timeout3telnet example.com8021|grepConnected# 提取域名对应的 IPnslookupexample.com2/dev/null|grepAddress|tail-1|awk{print $2}# 批量 pingecho8.8.8.8 1.1.1.1 8.8.4.4|xargs-n1ping-c1-W2# 生成 SSH 密钥并直接复制到远程ssh-keygen-trsa-f~/.ssh/id_rsa-Ncat~/.ssh/id_rsa.pub|sshuserhostmkdir -p ~/.ssh cat ~/.ssh/authorized_keys六、性能考量与限制6.1 管道缓冲区管道的缓冲区大小有限制Linux 上通常为 64KB可由ulimit -p查看# 产生大量数据时写入方会被阻塞yesdata|(sleep1;head-1)# yes 会因缓冲区满而暂停6.2 注意事项避免无用的 catUUOC — Useless Use of Cat# 不推荐catfile.txt|grepkeyword# 推荐grepkeywordfile.txt管道中的命令无法交互管道是非交互式的需要交互的命令如less、vim在管道中间没有意义。错误处理管道只传递 stdoutstderr 不会被传递。如需传递 stderrcommand21|greperror管道中的 exit 行为子 shell 中执行exit不会退出整个脚本需要使用set -o pipefail和PIPESTATUS来检查失败。二进制数据处理管道按字节流传输不关心内容是否为文本但某些文本处理工具如grep在遇到二进制数据时可能产生意外结果。七、管道与其他重定向的对比特性管道|输入重定向输出重定向连接方式命令 → 命令文件 → 命令命令 → 文件数据流向stdin ↔ stdout文件内容 → stdinstdout → 文件并发性两端并发N/AN/A中间文件不需要需要文件存在创建/覆盖文件组合使用# 从文件读取 → 管道处理 → 写入另一个文件input.txtsort|uniq-c|sort-rnoutput.txt# 多个输入源的合并处理sort(catfile1.txt)(catfile2.txt)|uniq# 错误重定向到文件同时管道正常输出command2error.log|grepkeywordresult.txt八、总结管道是 Linux 命令行的灵魂特性掌握它可以极大提升工作效率。核心要点|串联命令让数据像流水线一样传递grep、sort、uniq、wc、awk、sed是管道中最常用的处理工具xargs将管道输出转为命令行参数tee在管道中分流输出命名管道FIFO实现不相关进程间的通信进程替换( )让命令输出像文件一样使用注意管道中的子 shell 问题变量修改不会影响外部作用域管道的强大在于可组合性——一旦掌握了这些基本构件你可以像搭积木一样创建出强大而灵活的数据处理流水线。