欢迎光临
我们一直在努力

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

📌 博客原文链接:Breeze

在 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 513 09:22 0> /dev/pts/0 # 标准输入
lrwx——. 1 root root 64 513 09:22 1> /dev/pts/0 # 标准输出
lrwx——. 1 root root 64 513 09:21 2> /dev/pts/0 # 标准错误输出
lrwx——. 1 root root 64 513 09:22 3> /root/.1.txt.swp # 常规文件(vim 的交换文件)

分析:

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

总结:看到的 0、1、2、3 就是文件描述符(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'

分步拆解:

  • 第一步:cat /etc/passwd
    • 作用:把 /etc/passwd 这个文件的全部内容(系统里所有用户的信息)全部 “倒出来”
  • 第二步:|(管道)
    • 作用:把左边命令输出的所有内容,原封不动地通过 “水管” 传给右边的命令
  • 第三步: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?

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

    打个比方:

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

    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>&1 和 command 2>&1 > output.log 的效果是不同的。

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

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

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

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


    最佳实践

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

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

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

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

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

    command | tee output.log | less


  • 总结

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

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

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

    赞(0)
    未经允许不得转载:171主机测评 » 云计算基础-5:Linux 重定向与管道
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址