云计算基础-5:Linux 重定向与管道

在 Linux 的世界里,”一切皆文件”是核心哲学。重定向和管道正是这一哲学的最佳体现——它们让命令之间能够自由沟通、协作,将简单命令组合成强大的工作流。

很多初学者觉得重定向和管道难以理解,是因为没有搞清楚 Linux 是如何管理”输入”和”输出”的。本文将从最基础的文件描述符讲起,逐步带你掌握输出重定向、输入重定向、管道、tee、xargs 等核心工具,帮你打通 Linux 命令组合的任督二脉。


请思考

在深入重定向之前,让我们先思考一个问题:

如何让命令的输出持久保存?

  • 比如 date 命令输出的时间,关机重启后还能查看吗?
  • 答案当然是不能,因为输出只是显示在屏幕上,并没有保存下来
  • 解决办法:使用重定向 date > date.txt,把输出保存到文件中

文件描述符 FD

什么是文件描述符?

文件描述符(File Descriptors,简称 FD),也叫文件句柄。进程使用文件描述符来管理打开的文件。

举个简单例子说明:

想象你在图书馆借书:

  • 图书馆(操作系统)有很多书(文件)
  • 你不能直接去书架上拿书,而是需要通过借书卡(文件描述符)来获取书籍
  • 借书卡上的编号就是 FD,通过这个编号你才能读取或写入文件

标准输入、标准输出、标准错误

每个 Linux 进程启动时,系统会自动为它分配三个特殊的文件描述符:

FD 编号名称英文全称默认设备读写权限
0标准输入Standard Input (stdin)键盘只读
1标准输出Standard Output (stdout)屏幕只写
2标准错误Standard Error (stderr)屏幕只写
3+其他文件文件读写

观察 FD 信息

通过我们非常熟悉的 VIM 程序,来观察一个进程的 FD 信息。

步骤 1:打开一个文本文件

vim 1.txt

步骤 2:在另一个终端查询 vim 的进程号

ps aux | grep vim

输出示例:

root       9069  0.1  0.5 151532  5040 pts/0    S+   09:21   0:00 vim 1.txt

步骤 3:查看该进程的 FD 信息

通常在 /proc/PID/fd 就能看到文件的FD调用情况。

ls /proc/9069/fd

普通的 ls 可能看不出什么,加上 -l 参数试试:

ll /proc/9069/fd

输出示例:

总用量 0
lrwx------. 1 root root 64 5月  13 09:22 0 -> /dev/pts/0    # 标准输入
lrwx------. 1 root root 64 5月  13 09:22 1 -> /dev/pts/0    # 标准输出
lrwx------. 1 root root 64 5月  13 09:21 2 -> /dev/pts/0    # 标准错误输出
lrwx------. 1 root root 64 5月  13 09:22 3 -> /root/.1.txt.swp    # 常规文件(vim 的交换文件)

分析:

  • 012 都指向 /dev/pts/0(终端设备)
  • 3 指向 /root/.1.txt.swp(vim 编辑文件时自动创建的临时交换文件)

总结:看到的 0123 就是文件描述符(FD)。程序通过描述符访问文件,可以是常规文件,也可以是设备文件。FD 就像是进程的”借书卡”,通过它来读取或写入数据。


输出重定向

简介

输出重定向就是把命令的输出结果从屏幕上转移到文件中

打个比方:

正常情况下,命令的输出会”显示”在屏幕上(标准输出)。输出重定向就像给命令的输出换了个方向——不再显示在屏幕上,而是”写入”到一个文件中。

输出重定向的类型

输出分为正确输出(标准输出)错误输出(标准错误)

类型完整写法简写说明示例
正确输出 – 覆盖1>>覆盖写入,如果文件已存在则清空后重新写入date > date.txt
正确输出 – 追加1>>>>追加写入,在文件末尾添加内容date >> date.txt
错误输出 – 覆盖2>无简写仅将错误信息重定向到文件ls /aaa 2> error.txt
错误输出 – 追加2>>无简写将错误信息追加到文件末尾ls /aaa 2>> error.txt

记忆技巧

  • > 一个箭头表示覆盖(就像新来的把原来的替换掉)
  • >> 两个箭头表示追加(新来的跟在后面)

案例 1:正确输出重定向

覆盖写入:

[root@localhost ~]# date 1> date.txt

追加写入:

[root@localhost ~]# date >> date.txt

检验效果:

[root@localhost ~]# cat date.txt 
2026年 05月 13日 星期三 09:53:09 CST
2026年 05月 13日 星期三 09:54:42 CST
# 再次覆盖写入
[root@localhost ~]# date   >  date.txt 
[root@localhost ~]# cat date.txt 
2026年 05月 13日 星期三 09:55:12 CST

注意:任何程序都可以使用重定向!比如 mkdir -v /test > mkdir.log,只要程序本身有输出,就可以重定向。

案例 2:错误输出重定向

错误示范:

[root@localhost ~]# ls /home/ 2> list.txt

打开 list.txt 会发现没有任何内容,因为 ls /home/ 是一个正确的命令,没有产生错误信息。

正确示范:

[root@localhost ~]# ls /aaaaaaaaa 2> list.txt
[root@localhost ~]# cat list.txt
ls: 无法访问/aaaaaaaaa: 没有那个文件或目录

关键点:当某条命令产生错误时,才会有错误输出。错误输出重定向就是把这些”报错信息”从屏幕上转移到文件中。

案例 3:正确和错误都输入到相同位置

[root@localhost ~]# ls /home/ /aaaaaaaaa &> list.txt

&> 是 bash 的快捷写法,等价于 > file 2>&1,表示正确输出和错误输出都写入到同一个文件(这里的&1指的就是file这个文件,这里做个了解就行)。

生产环境实战:屏蔽所有输出

[root@localhost ~]# yum install httpd &>/dev/null

什么是 /dev/null

/dev/null 是 Linux 系统中的一个特殊设备文件,被称为黑洞。任何写入它的数据都会被丢弃,读取它什么也得不到。

当你不关心命令的输出时(比如自动化脚本中),可以把输出重定向到 /dev/null,避免产生大量日志文件。


输入重定向

简介

输入重定向 <(等价于 0<:把一个文件的内容作为命令的输入,代替手动键盘输入。

打个比方:

正常使用邮箱发送邮件时,你需要一行一行地输入邮件内容。如果已经有了现成的邮件内容文件,输入重定向就像”把文件内容喂给邮箱”,代替你手动输入。

cat 命令读取文件

cat 命令的默认行为是从标准输入(键盘)读取内容并打印到屏幕。输入重定向可以让它从文件读取内容。

步骤 1:不用重定向(从键盘输入)

cat

运行后光标会停在终端,你输入什么,它就会立刻打印什么。按 Ctrl+D 结束输入。

步骤2:用输入重定向(从文件读取)

# 先创建一个测试文件
echo "第一行内容" > test.txt
echo "第二行内容" >> test.txt
echo "第三行内容" >> test.txt

# 输入重定向:让cat从test.txt读取输入
cat < test.txt

运行结果:

第一行内容
第二行内容
第三行内容

原理

  • < test.txt 把标准输入(fd 0)从键盘重定向到文件 test.txt
  • cat 命令本身没有任何变化,它还是从 “标准输入” 读数据,只是这个 “标准输入” 现在指向了文件

管道

管道 |

简介

管道命令:将多条命令组合起来,一次性完成复杂的处理任务。

语法:

command1 | command2 | command3 | ...

形象理解:

管道就像一根水管:

  • 命令 1 的输出 = 水龙头流出的水
  • 管道 | = 水管
  • 命令 2 的输入 = 水管另一端接收的水

命令 1 的标准输出作为命令 2 的标准输入,形成一个数据流转的链条。

案例

# 查看 /etc/passwd 文件的最后 3 行
[root@localhost ~]# cat /etc/passwd | tail -3

# 查找 sshd 相关的进程
[root@localhost ~]# ps aux | grep 'sshd'

分步拆解:

  1. 第一步:cat /etc/passwd
    • 作用:把 /etc/passwd 这个文件的全部内容(系统里所有用户的信息)全部 “倒出来”
  2. 第二步:|(管道)
    • 作用:把左边命令输出的所有内容,原封不动地通过 “水管” 传给右边的命令
  3. 第三步:tail -3
    • 作用:只接收水管流过来的内容,然后只保留最后 3 行,其他全部扔掉

最终效果:不用打开整个文件翻到最后,一步直接看到系统用户文件的最后 3 行。

第二个示例也是同理,ps aux会静态显示所有进程,通过管道符把所有进程交给grep后,grep会筛选出于sshd相关的行作为结果输出


tee 管道(三通管道)

简介

tee 管道:三通管道,即把数据交给另一个程序继续处理,同时又保存一份副本到文件中。

形象理解:

想象一个 T 形水管三通头:

  • 水流(数据)从一端进入
  • 分成两路:一路继续向前流(交给下一个命令),一路分流到侧面(保存到文件)

案例

[root@localhost ~]# cat /etc/passwd | tee 88.txt | tail -1
jack:x:6674:6676::/home/jack:/bin/bash

查看 tee 保存的文件内容:

[root@localhost ~]# cat 88.txt

问题:88.txt 文件中是什么内容?一行还是所有行?

答案:所有行!因为 tee 保存的是命令 1(cat)处理的全部结果,而 tail -1 只是从管道中取走的最后一行。


参数传递 xargs

为什么需要 xargs?

有些命令(如 cprmmv)比较特殊,它们不接受管道的标准输入作为参数

打个比方:

管道就像传送带,把上一个命令的输出传递给下一个命令。但 rmcp 这些命令”脾气倔”,不吃传送带上的东西,只接受直接给它们的参数。

xargs 就是翻译官,把传送带上的内容”翻译”成这些命令能理解的参数格式。

案例演示

步骤 1:环境准备,创建一些文件

[root@localhost ~]# touch /home/file{1..5}
[root@localhost ~]# ls /home
file1  file2  file3  file4  file5

步骤 2:创建要删除的文件列表

[root@localhost ~]# vim files.txt
/home/file1
/home/file3
/home/file5

步骤 3:尝试直接用管道删除(失败)

[root@localhost ~]# cat files.txt | rm -rvf
# 查看/home下的文件,发现删除失败!rm 不会删除任何文件

为什么会失败? 因为 rm 不接受管道的标准输入作为参数。它需要的是 rm /home/file1 /home/file3 /home/file5 这种参数形式。

步骤 4:加上 xargs 成功连接 rm 命令

[root@localhost ~]# cat files.txt | xargs rm -rvf
已删除"/home/file1"
已删除"/home/file3"
已删除"/home/file5"

[root@localhost ~]# ls /home
file2  file4

xargs 的作用原理:

# 没有 xargs:
cat files.txt | rm -rvf
# rm 收到的是标准输入,但它看不懂

# 有 xargs:
cat files.txt | xargs rm -rvf
# xargs 把文件内容转换成参数格式:rm -rvf /home/file1 /home/file3 /home/file5

xargs 常用用法

# 查找所有 .log 文件并删除
find /var/log -name "*.log" | xargs rm -f

# 查找并统计行数
find . -name "*.txt" | xargs wc -l

# 处理文件名中包含空格的情况(使用 -d 指定分隔符)
find . -name "*.txt" -print0 | xargs -0 rm -f

综合场景(了解)

场景一:日志分析

# 查看访问日志中状态码为 404 的请求,并统计数量
cat /var/log/nginx/access.log | grep " 404 " | wc -l

# 查看错误日志并保存到文件
cat /var/log/nginx/error.log | tee /tmp/nginx_errors.txt | grep "critical"

场景二:批量文件操作

# 查找所有超过 100MB 的日志文件并删除
find /var/log -name "*.log" -size +100M | xargs rm -f

# 查找所有 .conf 配置文件并备份
find /etc -name "*.conf" | xargs -I {} cp {} {}.bak

场景三:自动化脚本中的输出管理

# 安装软件包,只保留错误输出
yum install -y nginx &>/dev/null

# 安装软件包,将日志追加到文件
yum install -y nginx >> /var/log/install.log 2>&1

常见问题

Q1:>>> 有什么区别?

操作符行为类比
>覆盖写入,清空文件后再写入把黑板擦干净再写新内容
>>追加写入,在文件末尾添加在黑板内容的最后一行继续写

Q2:2>&1 是什么意思?

2>&1 的含义是:把标准错误(FD 2)重定向到标准输出(FD 1)当前指向的位置

# 正确输出和错误输出都写入到同一个文件
command > output.log 2>&1

# 或者使用 bash 快捷写法
command &> output.log

注意:顺序很重要!command > output.log 2>&1command 2>&1 > output.log 的效果是不同的。

Q3:管道和重定向有什么区别?

| 特性 | 管道 | | 重定向 >< | |——|———|—————-| | 连接对象 | 命令与命令 | 命令与文件 | | 数据流向 | 命令1 的输出 → 命令2 的输入 | 命令的输出 → 文件,或 文件的输入 → 命令 | | 使用场景 | 组合多个命令处理数据 | 保存输出结果或读取文件内容 |

Q4:如何只保存正确输出,忽略错误输出?

# 正确输出保存到文件,错误输出丢弃到黑洞
command > output.log 2>/dev/null

最佳实践

  1. 重定向前先确认文件是否存在

    • > 会覆盖已有文件,谨慎使用
    • 不确定时使用 >> 追加
  2. 生产环境中合理管理输出

    • 不需要输出时用 &>/dev/null 避免产生无用日志
    • 需要追踪时用 >> 追加到日志文件
  3. 管道命令链不要太长

    • 一般建议不超过 3-4 个管道连接
    • 太长可考虑写成 shell 脚本
  4. 使用 xargs 处理大量文件时注意安全

    • 文件名含空格时使用 -print0-0 参数
    • 删除前先用 lsecho 预览
  5. 善用 tee 同时查看和保存输出


    command | tee output.log | less


总结

通过本文的学习,你应该掌握了:

  • 理解文件描述符(FD)的概念和作用
  • 使用 >>> 进行正确输出重定向
  • 使用 2>2>> 进行错误输出重定向
  • 使用 < 进行输入重定向
  • 使用 | 管道连接多个命令
  • 使用 tee 同时查看和保存输出
  • 使用 xargs 将标准输入转换为命令行参数

学习建议:重定向和管道是 Linux 命令行最强大的特性之一。建议在自己的虚拟机上多练习这些命令,尝试将不同命令组合起来,你会发现 Linux 命令行的无限可能!


🙋 学习路上不孤单,有坑一起填!



卡在参数调试、命令打架、功能没反应、资源失效?其他问题?直接戳我,也可以进群和同好交流!



📱 个人QQ:3838586495    👥 交流Q群:1094091455    📮 邮箱:leyan2504@163.com



内容帮你省了大把踩坑时间?可以文末小小打赏鼓励一波,也欢迎安利给身边学习的朋友~



✨ 欢迎来评论区「交作业」:分享你的配置思路、提出疑难问题;评论区正确填写邮箱,不错过任何人的解答回复!


暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇