1.Linux 输入输出重定向介绍

上图显示了 Unix/Linux 系统中进程(PROCESS)的输入输出流(I/O Streams)模型,核心是 “标准流(Standard Streams)” 的概念,用于描述进程如何与外部(如键盘、屏幕、文件)进行数据交互。

1.1标准流的核心组成

  • stdin(标准输入,编号 0)
  • 是进程接收输入数据的通道,默认连接到键盘,程序通过它读取用户输入(如 scanfread 等操作会从 stdin 获取数据)。
  • 用法为仅读取(只能从该通道输入数据到进程)。
  • stdout(标准输出,编号 1)
  • 是进程输出正常结果的通道,默认连接到终端屏幕,程序的普通打印(如 printfecho 等)会输出到 stdout
  • 用法为仅写入(进程只能向该通道输出数据)。
  • stderr(标准错误,编号 2)
  • 是进程输出错误信息的通道,默认也连接到终端屏幕,用于区分正常输出和错误提示(如程序崩溃、逻辑错误的提示信息)。
  • 用法为仅写入(专门用于输出错误内容)。
  • 3+ 号通道(其他文件,filename)
  • 代表进程与自定义文件的交互通道(非标准流),没有默认连接,需要手动指定文件。
  • 用法为读取和 / 或写入(可根据需求对文件进行读、写操作)。

1.2流程逻辑

  • 输入:用户通过键盘向 stdin 输入数据,进程从 stdin 读取这些输入。
  • 输出:进程将正常结果写入 stdout,错误信息写入 stderr,两者默认都显示在终端;同时,进程也可通过 3+ 号通道与其他文件进行数据的读写交互。

这种模型是 Unix/Linux 系统中 “一切皆文件” 思想的体现,让进程能以统一的方式处理不同来源 / 目标的数据,也为 重定向(Redirect) 等操作(如把 stdout 输出到文件、把文件内容作为 stdin 输入)提供了基础。

2.标准输出重定向到文件

# 查找 /etc 目录下 文件名是passwd的所有文件
[fengkai@fengkai ~ 18:59:23]$ find /etc -name passwd
find: ‘/etc/grub.d’: 权限不够
find: ‘/etc/pki/CA/private’: 权限不够
find: ‘/etc/pki/rsyslog’: 权限不够
/etc/pam.d/passwd
find: ‘/etc/dhcp’: 权限不够
/etc/passwd
find: ‘/etc/selinux/targeted/active’: 权限不够
.......

# 将找到的文件名清单覆盖写入到passwd.list文件中
[fengkai@fengkai ~ 18:59:41]$ find /etc -name passwd 1>passwd.list
find: ‘/etc/grub.d’: 权限不够
find: ‘/etc/pki/CA/private’: 权限不够
find: ‘/etc/pki/rsyslog’: 权限不够
find: ‘/etc/dhcp’: 权限不够
......
[fengkai@fengkai ~ 19:00:36]$ cat passwd.list 
/etc/pam.d/passwd
/etc/passwd

# 补充说明 
# 1>passwd.list可简写为>passwd.list
# 1和>之间不能有空格

# 将多个文件内容合并为1个,分别查看各个文件,的确是内容加在一起了
[fengkai@fengkai ~ 19:00:47]$ cat /etc/fstab /etc/hosts > allinone
[fengkai@fengkai ~ 19:01:56]$ cat allinone 

#
# /etc/fstab
# Created by anaconda on Tue Jul 14 10:25:59 2026
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=cf271b57-4d0f-4dc8-954a-92dc152a1304 /boot                   xfs     defaults        0 0
/dev/mapper/centos-home /home                   xfs     defaults        0 0
/dev/mapper/centos-swap swap                    swap    defaults        0 0
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

[fengkai@fengkai ~ 19:02:23]$ cat /etc/fstab

#
# /etc/fstab
# Created by anaconda on Tue Jul 14 10:25:59 2026
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=cf271b57-4d0f-4dc8-954a-92dc152a1304 /boot                   xfs     defaults        0 0
/dev/mapper/centos-home /home                   xfs     defaults        0 0
/dev/mapper/centos-swap swap                    swap    defaults        0 0

[fengkai@fengkai ~ 19:02:39]$ cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

# 将找到的文件名清单追加写入到passwd.list文件中
[fengkai@fengkai ~ 19:02:47]$ find /etc -name passwd 1>>passwd.list 
find: ‘/etc/grub.d’: 权限不够
find: ‘/etc/pki/CA/private’: 权限不够
find: ‘/etc/pki/rsyslog’: 权限不够
find: ‘/etc/dhcp’: 权限不够
......
[fengkai@fengkai ~ 19:05:30]$ cat passwd.list 
/etc/pam.d/passwd
/etc/passwd
/etc/pam.d/passwd
/etc/passwd

# 将错误信息覆盖写入到passwd.err文件中
[fengkai@fengkai ~ 19:05:36]$ find /etc -name passwd 2>passwd.err 
/etc/pam.d/passwd
/etc/passwd
[fengkai@fengkai ~ 19:06:36]$ cat passwd.err 
find: ‘/etc/grub.d’: 权限不够
find: ‘/etc/pki/CA/private’: 权限不够
find: ‘/etc/pki/rsyslog’: 权限不够
find: ‘/etc/dhcp’: 权限不够
......

# 将错误信息扔掉
[fengkai@fengkai ~ 19:06:45]$ find /etc -name passwd 2>/dev/null 
/etc/pam.d/passwd
/etc/passwd

# 将错误信息追加写入到passwd.err文件中
[fengkai@fengkai ~ 19:07:17]$ find /etc -name passwd 2>>passwd.err 
/etc/pam.d/passwd
/etc/passwd
[fengkai@fengkai ~ 19:07:52]$ cat passwd.err 
find: ‘/etc/grub.d’: 权限不够
find: ‘/etc/pki/CA/private’: 权限不够
find: ‘/etc/pki/rsyslog’: 权限不够
find: ‘/etc/dhcp’: 权限不够
find: ‘/etc/selinux/targeted/active’: 权限不够
find: ‘/etc/selinux/final’: 权限不够
find: ‘/etc/lvm/archive’: 权限不够
find: ‘/etc/lvm/backup’: 权限不够
find: ‘/etc/lvm/cache’: 权限不够
......

# 将错误信息、正确信息 覆盖 写入到不同文件
[fengkai@fengkai ~ 19:08:29]$ find /etc -name passwd >passwd.list 2>passwd.err
# 将错误信息、正确信息 追加 写入到不同文件
[fengkai@fengkai ~ 19:09:26]$ find /etc -name passwd >>passwd.list 2>>passwd.err

# 用于清空文件内容,也可用于创建一个空文件testfile
[fengkai@fengkai ~ 19:10:00]$ > test
[fengkai@fengkai ~ 19:10:05]$ vi test
[fengkai@fengkai ~ 19:10:59]$ head test
hello

# 如果不存在,则创建一个文件;如果文件存在,则啥也不干。
[fengkai@fengkai ~ 19:11:03]$ >> test
[fengkai@fengkai ~ 19:11:16]$ head test
hello

# 同时将错误信息、正确信息 覆盖 写入到相同文件
[fengkai@fengkai ~ 19:11:19]$ find /etc -name passwd &>passwd.all
[fengkai@fengkai ~ 19:12:53]$ cat passwd.all
find: ‘/etc/grub.d’: 权限不够
find: ‘/etc/pki/CA/private’: 权限不够
find: ‘/etc/pki/rsyslog’: 权限不够
/etc/pam.d/passwd
find: ‘/etc/dhcp’: 权限不够
/etc/passwd
·····

# 同时将错误信息、正确信息 追加 写入到相同文件
[fengkai@fengkai ~ 19:13:02]$ find /etc -name passwd &>>passwd.all
[fengkai@fengkai ~ 19:13:25]$ cat passwd.all
find: ‘/etc/grub.d’: 权限不够
find: ‘/etc/pki/CA/private’: 权限不够
find: ‘/etc/pki/rsyslog’: 权限不够
/etc/pam.d/passwd
find: ‘/etc/dhcp’: 权限不够
/etc/passwd
find: ‘/etc/selinux/targeted/active’: 权限不够
·····

3.标准输出重定向到程序

管道符(|)实现:将上一个命令的输出作为标准输入传递给下一个命令。

# 示例1 查看哪个man page 可以resize ext4文件系统大小

# 搜索所有ext4相关手册,并保存到ext4.man文件中
[fengkai@fengkai ~ 19:13:27]$ man -k ext4 >ext4.man
[fengkai@fengkai ~ 19:14:25]$ cat ext4.man 
debugfs (8)          - ext2/ext3/ext4 file system debugger
dumpe2fs (8)         - dump ext2/ext3/ext4 filesystem information
e2fsck (8)           - check a Linux ext2/ext3/ext4 file system
e2image (8)          - Save critical ext2/ext3/ext4 filesystem metadata to a file
e2label (8)          - Change the label on an ext2/ext3/ext4 filesystem
e2undo (8)           - Replay an undo log for an ext2/ext3/ext4 filesystem
e4defrag (8)         - online defragmenter for ext4 filesystem
ext4 (5)             - the fourth extended file system
·····

# 过滤ext4.man文件中含有resize的行
[fengkai@fengkai ~ 19:14:28]$ grep resizer ext4.man 
resize2fs (8)        - ext2/ext3/ext4 file system resizer

# 以上两个命令和合并为一行
[fengkai@fengkai ~ 19:15:00]$ man -k ext4 | grep resizer
resize2fs (8)        - ext2/ext3/ext4 file system resizer

# 示例2 获取ens33网卡ip地址
[fengkai@fengkai ~ 19:15:15]$ ip addr | grep 'ens33$' | awk '{print $2}'|cut -d/ -f1
10.1.8.10

注意:管道符号后的命令必须能够接收标准输入,例如 ls   接收管道传递过来的标准输入。

[fengkai@fengkai ~ 19:15:31]$ echo /etc/passwd | ls -l 
总用量 28
-rw-rw-r--. 1 fengkai fengkai  699 7月  16 19:01 allinone
-rw-r--r--. 1 fengkai fengkai  367 7月  16 18:44 dhcpd.conf
-rw-rw-r--. 1 fengkai fengkai 1294 7月  16 19:14 ext4.man
-rw-rw-r--. 1 fengkai fengkai 1594 7月  16 19:13 passwd.all
-rw-rw-r--. 1 fengkai fengkai 1534 7月  16 19:09 passwd.err
-rw-rw-r--. 1 fengkai fengkai   60 7月  16 19:09 passwd.list
-rw-rw-r--. 1 fengkai fengkai    6 7月  16 19:10 test
drwxr-xr-x. 2 fengkai fengkai    6 7月  14 10:39 公共
drwxr-xr-x. 2 fengkai fengkai    6 7月  14 10:39 模板
drwxr-xr-x. 2 fengkai fengkai    6 7月  14 10:39 视频
drwxr-xr-x. 2 fengkai fengkai    6 7月  14 10:39 图片
drwxr-xr-x. 2 fengkai fengkai    6 7月  14 10:39 文档
drwxr-xr-x. 2 fengkai fengkai    6 7月  14 10:39 下载
drwxr-xr-x. 2 fengkai fengkai    6 7月  14 10:39 音乐
drwxr-xr-x. 2 fengkai fengkai   25 7月  14 11:08 桌面

补充:|& 标准错误和标准输出同时传递给下一个命令,作为下一个命令的标准输入。

[fengkai@fengkai ~ 19:18:55]$ touch file-{01..03}
[fengkai@fengkai ~ 19:19:08]$ ls
allinone    ext4.man  file-02  passwd.all  passwd.list  公共  视频  文档  音乐
dhcpd.conf  file-01   file-03  passwd.err  test         模板  图片  下载  桌面

[fengkai@fengkai ~ 19:19:09]$ ls -l file-{01..06}
ls: 无法访问file-04: 没有那个文件或目录
ls: 无法访问file-05: 没有那个文件或目录
ls: 无法访问file-06: 没有那个文件或目录
-rw-rw-r--. 1 fengkai fengkai 0 7月  16 19:19 file-01
-rw-rw-r--. 1 fengkai fengkai 0 7月  16 19:19 file-02
-rw-rw-r--. 1 fengkai fengkai 0 7月  16 19:19 file-03

[fengkai@fengkai ~ 19:19:51]$ ls -l file-{01..06} | grep file-06
ls: 无法访问file-04: 没有那个文件或目录
ls: 无法访问file-05: 没有那个文件或目录
ls: 无法访问file-06: 没有那个文件或目录

[fengkai@fengkai ~ 19:20:22]$ ls -l file-{01..06} | grep file-03
ls: 无法访问file-04: 没有那个文件或目录
ls: 无法访问file-05: 没有那个文件或目录
ls: 无法访问file-06: 没有那个文件或目录
-rw-rw-r--. 1 fengkai fengkai 0 7月  16 19:19 file-03

# |&
[fengkai@fengkai ~ 19:20:43]$ ls -l file-{01..06} |& grep file-06
ls: 无法访问file-06: 没有那个文件或目录

4.tee 命令

tee 命令作用,接收管道传递过来的stdin,并继续作为stdout输出。

[fengkai@fengkai ~ 19:23:20]$ > passwd.list 
[fengkai@fengkai ~ 19:23:46]$ cat passwd.list 
[fengkai@fengkai ~ 19:23:52]$ 
# tee命令覆盖保存到文件
[fengkai@fengkai ~ 19:24:14]$ find /etc -name passwd 2>/dev/null | tee passwd.list 
/etc/pam.d/passwd
/etc/passwd
[fengkai@fengkai ~ 19:24:47]$ cat passwd.list 
/etc/pam.d/passwd
/etc/passwd

# tee命令追加保存到文件
[fengkai@fengkai ~ 19:25:29]$ find /etc -name passwd 2>/dev/null | tee -a passwd.list 
/etc/pam.d/passwd
/etc/passwd
[fengkai@fengkai ~ 19:25:50]$ cat passwd.list 
/etc/pam.d/passwd
/etc/passwd
/etc/pam.d/passwd
/etc/passwd

# tee的标准输出继续通过管道传递下去
[fengkai@fengkai ~ 19:25:52]$ man -k passwd | tee passwd.man | grep passwd
chgpasswd (8)        - 批量更新组密码
chpasswd (8)         - 批量更新密码
·····
saslpasswd2 (8)      - set a user's sasl password
vncpasswd (1)        - change the VNC password
[fengkai@fengkai ~ 19:26:22]$ cat passwd.man 
chgpasswd (8)        - 批量更新组密码
chpasswd (8)         - 批量更新密码
·····
saslpasswd2 (8)      - set a user's sasl password
vncpasswd (1)        - change the VNC password

5.标准输入重定向给程序

# 常规查看文件
[fengkai@fengkai ~ 19:29:51]$ cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

# cat 命令标准输入数据
[fengkai@fengkai ~ 19:29:56]$ cat < /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

[fengkai@fengkai ~ 19:29:58]$ cat(回车)
hello  # 键盘输入hello后回车
hello  # 屏幕上显示hello
ctrl+d # 输入完成,退出

# shell读取到EOF时候,代表标准输入完成
[fengkai@fengkai ~ 19:32:16]$ cat << EOF
> hello
> world
> eof
> EOF
hello
world
eof

# 使用<<<直接输出
[fengkai@fengkai ~ 19:33:19]$ cat <<< 'hello world'
hello world

==判定一个命令是否接收标准输入==:最简单的方式就是将文件内容作为标准输入重定向给程序。

思考:如何一次性将多行内容写入到文件中?

# 方法1:使用引号
[fengkai@fengkai ~ 19:35:12]$ echo 'hello world
hello
linux' > multi_lines.txt
[fengkai@fengkai ~ 19:35:53]$ cat multi_lines.txt 
hello world
hello
linux

# 方法2:使用cat重定向
[fengkai@fengkai ~ 19:35:59]$ cat > multi_lines.txt << EOF
> 1
> 2
> 3
> EOF
[fengkai@fengkai ~ 19:37:13]$ cat multi_lines.txt 
1
2
3

6.综合测试(无标准答案,看自己理解,以下为我的理解)

1.你对谈谈你对输出重定向的理解,用示例说明。

  正常敲完命令之后如find /etc -name passwd,屏幕之上有回显,有正确的(1)和错误的(2),我们可以将这些进行分类处理,将正确的通过find /etc -name passwd 1>xxx.txt收集到xxx.txt中,将错误的通过find /etc -name passwd 2>yyy.txt收集到yyy.txt中。

  >每执行过一次就会覆盖,可以通过>>就会持续收集。

2.谈谈你对管道符(|)的理解,用示例说明。

  通过对当前命令的输出信息进行二次的匹配筛选,获取想要的数据,可以多次使用,直到匹配出你想要的结果。

[fengkai@fengkai ~ 19:15:15]$ ip addr | grep 'ens33$' | awk '{print $2}'|cut -d/ -f1
10.1.8.10

3.谈谈你对tee命令的理解,用示例说明。

  配合|符使用,将当前显示的数据,存储到相应的文件中,find /etc -name passwd 2>/dev/null | tee passwd.list ,为了防止覆盖,可以加-a

find /etc -name passwd 2>/dev/null | tee -a passwd.list 

4.谈谈你对标准输入重定向的理解,用示例说明。

  将文件内容重新输入给程序,如 cat < /etc/hosts

  或者直接输出,如 cat <<< 'hello world'

  配合>将内容写入到文件中,如 cat > multi_lines.txt << EOF

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐