Linux 管道与重定向入门:把命令串起来的高级玩法
在日常的 Linux 使用中,我们经常把一条命令的输出交给下一条命令处理,比如 cat access.log | grep "500" | wc -l。这条管道背后其实是两个功能在协同工作:管道(pipe)负责把标准输出接到下一条命令的标准输入,重定向(redirection)负责把标准输出或标准错误写入文件。
一、三种标准流
每个进程默认拥有三个文件描述符:
- 0 标准输入(stdin):读取数据的入口,通常连着键盘;
- 1 标准输出(stdout):正常结果的出口,默认输出到终端;
- 2 标准错误(stderr):错误信息的出口,同样默认输出到终端。
我们平常敲的 ls -l > result.txt 就是把 fd 1 重定向到文件;ls -l 2> error.txt 则把 fd 2 单独写进文件。当两个流都指向同一个文件时,可以写成 ls -l > all.txt 2>&1,注意 2>&1 的顺序不能颠倒。
二、输出重定向的三种写法
最常用的是覆盖与追加:
command > file.txt # 覆盖写入,原内容丢失
command >> file.txt # 追加写入,保留原内容
command 2> file.txt # 只重定向错误输出
command > file.txt 2>&1 # 正常与错误输出都写入同一文件
command &> file.txt # 等价于上一行(Bash 支持)
排查线上脚本时,我最常用的是 ./deploy.sh > deploy.log 2>&1,这样既能保留正常的部署进度,也能把报错一起收进日志。
三、输入重定向与 Here Document
输入重定向用 <,把文件作为命令的标准输入:
wc -l < notes.txt
sort < names.txt > sorted.txt
如果只是想临时喂一段固定文本给命令,Here Document 更方便:
cat << EOF
hello
world
EOF
也可以用 <<-EOF,它允许缩进结束标记,更适合在脚本中嵌入 YAML 或 SQL。
四、管道:把命令串成流水线
管道符 | 把左侧命令的标准输出直接接到右侧命令的标准输入,中间不落盘,因此非常高效:
ps aux | grep nginx | grep -v grep | awk '{print $2}' | xargs kill -9
这条命令依次完成了:列出进程、筛选 nginx 相关进程、去掉 grep 自身、提取 PID、再批量结束进程。每一个环节只做一件事,组合起来就非常强大。
需要注意的是,管道右侧命令的退出状态才是整条命令的退出状态。如果右侧没有匹配到数据(比如 grep 没找到),整条命令依然会返回非零退出码,所以写脚本时要在意这一点。
五、tee:既看屏幕又存文件
tee 是管道的常客。它把标准输入复制到标准输出,同时写入文件:
make 2>&1 | tee build.log
这样既能在终端实时看到编译过程,又保留了完整日志。配合 tee -a 还能追加写入。
六、实战:用管道快速定位问题
下面几个组合在日常排障里非常实用:
# 统计日志里各状态码出现次数
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 找出占用内存最多的三个进程
ps aux --sort=-%mem | head -4
# 提取配置文件里的非注释行
grep -vE '^\s*(#|$)' /etc/nginx/nginx.conf
# 实时过滤关键字并高亮
tail -f app.log | grep --color=always "ERROR"
七、常见陷阱
- 忘了写管道两端的空格:
cat file|grep x其实能工作,但阅读体验很差,建议保持空格。 - 用管道传递二进制数据:管道是面向字节流的,传输大文件时用
cp或rsync更合适。 - 重定向顺序写错:
2>&1 > file与> file 2>&1的结果完全不同,前者错误输出仍然留在终端。 - 管道里用 sudo:sudo 只会作用于管道右侧命令,左侧仍以普通用户身份运行,容易造成权限不一致。
八、小结
重定向解决的是"数据去哪",管道解决的是"数据怎么走"。把两者结合,再加上 grep、awk、sed、sort、uniq 这些文本处理工具,就能用很少的代码完成复杂的数据清洗与排查工作。建议大家从收藏几个常用组合开始,慢慢把命令行练成自己的瑞士军刀。
- 点赞
- 收藏
- 关注作者
评论(0)