前言
首先,我们得知道,linux 系统会将用户的每个请求对象都当作一个文件,输入输出也不例外。那么,我们就得知道进行输入与输出的文件都是什么?都有那些?
如果每个对象都需要文件,那么对文件就应该有标识以便区分。因此就需要文件描述符。文件描述符是一个非负整数,可以唯一地标识会话中打开的文件,每个过程一次最多可以有9个文件描述符,出于特殊目的,bash shell 保留了最早的3个文件描述符(0、1、2)。
下图为输入一个命令后系统所进行的一系列操作:
输入输出
-
输入
stdin[标准输入流]
输入是指系统外界向系统中传入的信息,编号为0 -
输出
stdout[标准正确输出流]
在命令顺利执行后产生的字符串,编号为1
stderr[标准错误输出流]
在命令执行失败后产生的字符串,编号为2 -
字符设备
指在I/O传输过程中以字符为单位进行传输的设备,如键盘,打印机等。
字符设备是内存中开启的虚拟设备并且真实存在
重定向输出
符号 | 用途 |
---|---|
> | 重定向正确输出 |
2> | 重定向错误输出 |
&> | 重定向所有输出 |
输入输出示例
[student@workstation Desktop]$ find /etc/ -name passwd //输入命令,寻找passwd
find: ‘/etc/pki/rsyslog’: Permission denied //结果如下
find: ‘/etc/dhcp’: Permission denied
/etc/pam.d/passwd
/etc/passwd
find: ‘/etc/polkit-1/rules.d’: Permission denied
find: ‘/etc/polkit-1/localauthority’: Permission denied
find: ‘/etc/sssd’: Permission denied
find: ‘/etc/grub.d’: Permission denied
find: ‘/etc/audit’: Permission denied
find: ‘/etc/firewalld’: Permission denied
find: ‘/etc/sudoers.d’: Permission denied
find: ‘/etc/lvm/archive’: Permission denied
find: ‘/etc/lvm/backup’: Permission denied
find: ‘/etc/lvm/cache’: Permission denied
find: ‘/etc/libvirt’: Permission denied
find: ‘/etc/cups/ssl’: Permission denied
可以看出,除了有两条正确输出外其他都是错误输出。
我们可以去找一下输出这些的文件
进程信息
[student@workstation Desktop]$ ps
PID TTY TIME CMD
2684 pts/0 00:00:00 bash
3023 pts/0 00:00:00 ps
进程id为2684,去proc/2684/fd文件
我们是不能打开这些文件的,但我们可以看到进程中却是存在这些输入输出文件
重定向输出示例
- ‘>’
如下所示:将结果重定向到test,test中会存在find的正确结果,而将错误的结果会输出到屏幕
[student@workstation Desktop]$ find /etc -name passwd > test
find: ‘/etc/pki/rsyslog’: Permission denied
find: ‘/etc/dhcp’: Permission denied
find: ‘/etc/polkit-1/rules.d’: Permission denied
find: ‘/etc/polkit-1/localauthority’: Permission denied
find: ‘/etc/sssd’: Permission denied
find: ‘/etc/grub.d’: Permission denied
find: ‘/etc/audit’: Permission denied
find: ‘/etc/firewalld’: Permission denied
find: ‘/etc/sudoers.d’: Permission denied
find: ‘/etc/lvm/archive’: Permission denied
find: ‘/etc/lvm/backup’: Permission denied
find: ‘/etc/lvm/cache’: Permission denied
find: ‘/etc/libvirt’: Permission denied
find: ‘/etc/cups/ssl’: Permission denied
- ‘2>’
如下所示:将结果重定向到test,test中会存在find的错误结果,而将正确的结果会输出到屏幕
[student@workstation Desktop]$ find /etc -name passwd 2> test
/etc/pam.d/passwd
/etc/passwd
- ‘&>’
如下所示:将全部结果重定向到test,屏幕上并不会出现任何信息
[student@workstation Desktop]$ find /etc -name passwd &> test
此时让我们打开test文件查看一下
追加
在重定向操作中,会覆盖源文件,如果源文件中的内容之后还要用到,我们只是希望将新文件追加到源文件之后,就需要用到追加
符号 | 用途 |
---|---|
>> | 追加正确输出 |
2>> | 追加错误输出 |
&>> | 追加全部输出 |
具体操作效果仅与重定向稍许不同,可参见重定向的操作
管道
把输出变成下一条命令的输入
(有时候我们需要一些高级的更复杂的操作,比如一条命令得到的结果变成下一条命令的作用对象,这这时候我们就需要管道来帮助我们)
符号 | 用途 |
---|---|
I | 管道符 |
2>&1 | 将编号为1的输出转换为2 |
tee | 复制输出到指定位置 |
现在我们来想一个需求,对上面找到的passwd文件进行计数。
我们可以先将找到的结果存储到一个文件中,在对新产生的文件计算行数,这个行就是文件的个数,在不知道管道的时候,我们需要两条命令来完成这个操作,但了解了管道,一条命令就可以操作。但是,不仅如此,管道带给我们的好处是能节省我们不少的时间,因为对磁盘文件里面的计数与对内存中的计数时间是不一样的。
-
‘|’ 将正确结果计数
[student@workstation Desktop]$ find /etc -name passwd | wc -l find: ‘/etc/pki/rsyslog’: Permission denied find: ‘/etc/dhcp’: Permission denied find: ‘/etc/polkit-1/rules.d’: Permission denied find: ‘/etc/polkit-1/localauthority’: Permission denied find: ‘/etc/sssd’: Permission denied find: ‘/etc/grub.d’: Permission denied find: ‘/etc/audit’: Permission denied find: ‘/etc/firewalld’: Permission denied find: ‘/etc/sudoers.d’: Permission denied find: ‘/etc/lvm/archive’: Permission denied find: ‘/etc/lvm/backup’: Permission denied find: ‘/etc/lvm/cache’: Permission denied find: ‘/etc/libvirt’: Permission denied find: ‘/etc/cups/ssl’: Permission denied 2
可以看出结果为2
-
‘2>&1’正误结果都计数
[student@workstation Desktop]$ find /etc -name passwd 2>&1 | wc -l 16
-
‘tee’记录消息
tee命令相当于管道的一个T型接头,它将从输入过来的数据
同时发给两个目的地。计数结果
[student@workstation Desktop]$ find /etc -name passwd 2>&1 |tee test |wc -l 16
打开test文件
find: ‘/etc/pki/rsyslog’: Permission denied find: ‘/etc/dhcp’: Permission denied /etc/pam.d/passwd /etc/passwd find: ‘/etc/polkit-1/rules.d’: Permission denied find: ‘/etc/polkit-1/localauthority’: Permission denied find: ‘/etc/sssd’: Permission denied find: ‘/etc/grub.d’: Permission denied find: ‘/etc/audit’: Permission denied find: ‘/etc/firewalld’: Permission denied find: ‘/etc/sudoers.d’: Permission denied find: ‘/etc/lvm/archive’: Permission denied find: ‘/etc/lvm/backup’: Permission denied find: ‘/etc/lvm/cache’: Permission denied find: ‘/etc/libvirt’: Permission denied find: ‘/etc/cups/ssl’: Permission denied
可见既进行的保存文件,又进行了文件的计数
(注意:tee命令会在每次使用时覆盖输出文件内容,如果你想将数据追加到文件中,必须使用-a选项。)
输入重定向
-
‘<’ 输入重定向
用符号从文件中获取输入
例如:我们现在想要将一个文件的大小写对换。tr命令可以将一个文件的大小写统一,那么首先得打开一个文件,再对文件进行tr操作。
原来文件:[root@workstation ~]# cat test Hello world My name is Hai Zhizhuer
利用管道进行更改:
[root@workstation ~]# cat test | tr 'a-z' 'A-Z' HELLO WORLD MY NAME IS HAI ZHIZHUER
然而利用管道在此时就显得没那么高效,使用重定向输入来看看:
[root@workstation ~]# tr 'A-Z' 'a-z' < test hello world my name is hai zhizhuer
相当于将test文件作为tr命令的输入。
-
'<<'多行输入
例如:如果我们要重置密码,就得输入两边新的密码,来确保自己的密码没有因为手误而输错。此时就可使用多行输入。而这个命令更多的应用于bash脚本,可帮助我们自动化的配置某些文件。paswd << HAI >redhat >redhat >HAI
上述代码中使用到的HAI这个关键字是任意的,可以输入任何你觉得ok的关键字,但注意,若系统监测到与多行输入后你输入的关键字一样的关键字,即认为输入结束。
一般标准情况下,我们使用EOF:
我们打开一个.sh的文件vim test1.sh
并输入如下文字且保存
date passwd << EOF redhat redhat EOF tr 'a-z' 'A-Z' < test
然后执行这个.sh文件
bash test.sh
结果会逐一执行上述命令。
显示date信息 对密码进行重置 将test文件中的小写全部换成大写
(注意:重定向输入与多行输入并无逻辑上的必然关系。)
总结
输入输出操作对于每一个计算机使用者来说都是必不可少的,所以,如何控制输入输出为我们日常需求来工作是运维工程师必须具备的技能。重定向与管道的引入对我们会非常有帮助。