本篇是Linux小白最佳实践第5篇,目的就是让白菜们了解Linux进程之间是如何对话的。之前连载的几篇,在微信上引起了很多的反响,有人也反映图多文字少,感觉没有干货.本篇选了大部分是实战讲解的"管道与重定向"进行连载,希望让读者能真正学到东西.
想每天能听到小妞的语音播报,想学更多学校里和书本上学不大的IT技术或技能,欢迎关注微信公众号:xiniubook2008。或加微博:我的图书我做主,参加活动,免费获书。
管道与重定向是Linux系统进程间的一种通讯方式,在系统管理中有着举足轻重的作用。绝大部分Linux进程运行时需要使用3个文件描述符:标准输入、标准输出和标准错误输出,对应的序号是0、1和2。一般来说,这3个描述符与该进程启动的终端相关联,其中输入一般为键盘。重定向和管道的目的是重定向这些描述符。管道一般为输入和输出重定向的结合,一个进程向管道的一端发送数据,而另一个进程从该管道的另一端读取数据。管道符是“|”。
执行一个Shell命令行时通常会自动打开3个标准文件,如图8.3所示。
图 8.3 Shell执行时对应的3个标准文件
标准输入文件stdin,通常对应终端的键盘,标准输出文件stdout和标准错误输出文件stderr,这两个文件都对应终端的屏幕。进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而错误信息将打印到标准错误文件。
现以cat 命令为例来介绍标准输入与输出。cat命令的功能是从命令行给出的文件中读取数据,并将这些数据直接送到标准输出文件,一般对应终端屏幕,如示例8-7所示。
【示例8-7】
[root@CentOS ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
HWADDR=00:0C:29:7F:08:9D
TYPE=Ethernet
UUID=3268d86a-3245-4afa-94e0-f100a8efae44
ONBOOT=yes
BOOTPROTO=static
BROADCAST=192.168.3.255
IPADDR=192.168.3.100
NETMASK=255.255.255.0
该命令会把文件ifcfg-eth0的内容显示到标准输出即屏幕上。如果cat命令行中没有参数,会从标准输入文件中一般对应键盘读取数据,并将其送到标准输出文件中,如示例8-8所示。
【示例8-8】
#cat不带任何参数时会从标准输入中读取数据并显示到标准输出文件中
[root@CentOS ~]# cat
mycontent
mycontent
hello
hello
用户输入的每一行信息都会立刻被cat命令输出到屏幕上。用户对输入的数据无法做进一步地处理。为解决这个问题,Linux操作系统为输入、输出的传送引入了另外两种机制:输入/输出重定向和管道。
输入重定向是指把命令或可执行程序的标准输入重定向到指定的文件中。也就是输入可以不来自键盘,而来自一个指定的文件。输入重定向主要用于改变一个命令的输入源。
例如上个示例中的cat命令,当键入该命令后并没有任何反应,从键盘输入的所有文本都出现在屏幕上,直至按下Ctrl+d组合键,命令才会终止,可采用两种方法:一种是为该命令给出一个文件名,另外一种方法是使用输入重定向。
输入重定向的一般形式为:命令<文件名,输入重定向符号为“<”。示例8-9演示了此种情况,此示例中的文件已不是参数,而是标准输入。
【示例8-9】
[root@CentOS ~]# cat< /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
HWADDR=00:0C:29:7F:08:9D
TYPE=Ethernet
UUID=3268d86a-3245-4afa-94e0-f100a8efae44
ONBOOT=yes
BOOTPROTO=static
BROADCAST=192.168.3.255
IPADDR=192.168.3.100
NETMASK=255.255.255.0
[root@CentOS ~]# wc </etc/sysconfig/network-scripts/ifcfg-eth0
99 188
还有一种输入重定向,如示例8-10所示。
【示例8-10】
[root@CentOS ~]# cat <<EEE
> line1
> line2
> line3
> EEE
line1
line2
line3
标识符“EEE”表示输入开始和结束的分隔符,此名称不是固定的,可以使用其他字符串,主要是一个分隔的作用。文档的重定向操作符为“<<”。将一对分隔符之间的正文重定向输入命令。例如上述示例中将“EEE”之间的内容作为正文,然后作为输入传给cat命令。由于大多数命令都以参数的形式在命令行中指定输入文件的文件名,所以输入重定向并不经常使用。使用某些不能利用文件名作为输入参数的命令,需要的输入内容又存在一个文件里时,可以用输入重定向来解决问题。
输出重定向是指把命令或可执行程序的标准输出或标准错误输出重新定向到指定文件中。命令的输出不显示在屏幕上,而是写入到指定的文件中,以便以后的问题定位或其他用途。输出重定向比输入重定向更常用,很多情况下都可以使用这种功能。例如,如果某个命令的输出很多,在屏幕上不能完全显示,那么将输出重定向到一个文件中,然后再用文本编辑器打开这个文件,就可以查看输出信息,如果想保存一个命令的输出,也可以使用这种方法。还有,输出重定向可用于把一个命令的输出当作另一个命令的输入,还有一种更简单的方法,就是使用管道,管道将在下节介绍。
输出重定向的一般格式为:命令>文件名,即输出重定向符号为“>”,使用方法如示例8-11所示。
【示例8-11】
#将输出重定向到文件
[root@CentOS ~]# ls -l / >dir.txt
[root@CentOS ~]# head-n5 dir.txt
total 114
dr-xr-xr-x.2 root root4096 Jun8 00:54 bin
dr-xr-xr-x.5 root root1024 Apr 13 00:33 boot
dr-xr-xr-x.7 root root4096 Mar6 02:33 cdrom
drwxr-xr-x.18 root root4096 Jun8 01:07 data
用“ls -l”命令显示当前的目录和文件,并把结果输出到当前目录下的dir.txt文件内,而不是显示在屏幕上。查看dir.txt文件的内容可以使用cat命令,注意是否与直接使用“ls -l”命令时的显示结果相同。
注意:如果“>”符号后面的文件已存在,那么这个文件将被覆盖。
为避免输出重定向命令中指定的文件内容被覆盖,Shell提供了输出重定向的追加方法。输出追加重定向与输出重定向的功能类似,区别仅在于输出追加重定向的功能是把命令或可执行程序的输出结果追加到指定文件的最后,这时文件的原有内容不被覆盖。追加重定向操作符“>>”,格式为:命令>>文件名,使用方法如示例8-12所示。
【示例8-12】
#使用重定向追加文件内容
[root@CentOS ~]# ls-l /usr >>dir.txt
上述命令的输出会追加在文件的末位,原来的内容不会被覆盖。
和程序的标准输出重定向一样,程序的错误输出也可以重新定向。使用符号“2>”或追加符号“2>>”标识可以对错误输出重定向。如要将程序的任何错误信息打印到文件中,以备问题定位,可以使用示例8-13中的方法。
【示例8-13】
#文件不存在,此时产生标准错误输出,一般为屏幕。
[root@CentOS ~]# ls /xxxx
ls: cannot access /xxxx: No such file or directory
#编号1表示重定向标准输出,但并不是错误输出吗,此时输出仍打印到屏幕上
[root@CentOS ~]# ls /xxxx 1>stdout
ls: cannot access /xxxx: No such file or directory
#分别重定向标准输出和标准错误输出
[root@CentOS ~]# ls /xxxx 1>stdout 2>stderr
#查看文件内容,和打印到屏幕的结果一致
[root@CentOS ~]# cat stderr
ls: cannot access /xxxx: No such file or directory
#将标准输出和标准错误输出都定向到标准输出文件
[root@CentOS ~]# ls /xxxx 1>stdout 2>&1
[root@CentOS ~]# cat stdout
ls: cannot access /xxxx: No such file or directory
#另外一种重定向的语法
[root@CentOS ~]# ls /xxxxx &>stderr
[root@CentOS ~]# ls /xxxxx/ &>stdout
#查看输出文件内容
[root@CentOS ~]# head stdout
ls: cannot access /xxxxx: No such file or directory
/:
bin
boot
cdrom
由于/xxxx目录不存在,所以没有标准输出,只有错误输出。上述示例首先演示了错误输出的内容,当标准输出被重定向后,标准错误输出并没有被重定向,所以错误输出被打印到屏幕上。使用“2>stderr”将错误输出定位到指定的文件中,另外一种方法是将标准错误输出重定向到标准输出,执行后在屏幕上看不到任何内容,用cat命令查看文件的内容,看到上面命令的错误提示。还可以使用另一个输出重定向操作符“&>”,其功能是将标准输出和错误输出送到同一文件中。表8-3列出了常用的输入输出重定向方法。
表8.3常用的重定向含义
参数 |
说明 |
command > filename |
把标准输出重定向到一个文件 |
command >> filename |
把标准输出追加重定向到一个文件 |
command 1> fielname |
把标准输出重定向到一个文件 |
command > filename 2 > &1 |
把标准输出和标准错误输出重定向到一个文件 |
command 2 > filename |
把标准错误输出重定向到一个文件中 |
command < filename > filename2 |
以filename为标准输入,filename2为标准输出 |
command < filename |
把filename作为命令的标准输入 |
command << delimiter |
从标准输入读入数据,直到遇到delimiter为止 |
将一个程序或命令的输出作为另一个程序或命令的输入,有两种方法:一种是通过一个临时文件将两个命令或程序结合在一起;另外一种方法是使用管道。
管道可以把一系列命令连接起来,可以将前面命令的输出作为后面命令的输入,第1个命令输出利用管道传给第2个命令,第2个命令的输出又会作为第3个命令的输入,以此类推。如果命令行中未使用输出重定向,显示在屏幕上的是管道行中最后一个命令的输出或其他命令执行异常时导致的错误输出。使用管道符“|”来建立一个管道行,用法如示例8-14所示。
【示例8-14】
[root@CentOS ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0|grep IPADD
IPADDR=192.168.3.100
#管道后接管道
[root@CentOS ~]# cat /etc/sysconfig/network-scripts/ifcfg-eth0|grep IPADD|awk -F= '{print $2}'
192.168.3.100
上述示例cat命令输出的内容以管道的形式发送给grep命令,然后通过字符串匹配查找文件内容。
喜欢可以购买《超容易的Linux系统管理入门书》。写书评得奖品。