一、标准输入和标准输出
终端程序一般以流的形式读取信息,如:从键盘读取信息。之后以流的形式写入目的地,如显示器。
在linux中标准输入是:stdin(键盘),标准输出是:stdout(显示器)
(一)将输出写入文件
一般把输出写到标准输出流中,这样就在显示器中显示了。但bash shell可以通过 > 重定向运算符把流向标准输出流的数据重定向到文件中。比如:
linux@myccloves:~/test$ ps aux > 1
当执行ps aux时,程序的结果输出到标准输出流中,所以在显示器中显示,但现在通过重定向输出到文件中了。
(二)把输出追加到文件中
当我们第一次把数据写到文件“1”中,再运行一次则会覆盖文件“1”,这样造成原先数据丢失。为了解决这类问题,可以把输出追加到文件中。如:
ps aux >> 1
用两个 > 就可以了。
(三)重定向标准输入
我们从键盘输入数据,流向程序中。换一种说法就是从键盘读取数据,现在我想从文件中读取数据。
我们以mail命令来说明这个问题:(我的测试环境是在虚拟机中:centos系统)
先来说点题外话:mail命令可以在终端发送电子邮件,但是必须进行mail的配置和网页端邮件的配置,老陌已经配置完,所以可以发送电子邮件。
回正题,我们通过mail命令发送电子邮件,其中 -s 表示信的标题,后面的邮箱表示发送给谁(目的邮箱)。 之后是重点,mail等用户输入正文…… 输入完成按ctrl+d结束输入,之后自动发送。这里面通过键盘也就是标准输入,输入数据到mail程序中,如果我们能够从其它地方输入数据,而不是从键盘,就需要用到重定向标准输入。
程序 < 文件
本来程序,通过键盘输入,现在通过文件进行输入,也就是把文件的内容送到程序里。如:
这一次我们发现,程序并没有让我们输入正文,原因是正文在letter这个文件里,通过重定向 <letter改变了标准输入,原先从键盘中读取数据,现在从letter文件中读取数据。
如果您感觉mail命令无法测试,可以用cat
cat命令原先从键盘读取数据,后来用 <letter,则从letter中读取数据了。
二、标准错误
标准错误和标准输出基本一样,标准错误也是一个输出流,用来报告出错状态信息,称为: stderr
我们来看一下例子来理解标准错误:
首先 head -2 /etc/passwd 输出的信息送到标准输出流中。
之后 head -2 /etc/shadow 输出的信息原先准备送到标准输出流中,但遇到了错误,所以送到标准错误输出流中,此时发现他们一样,怎么能说明这条命令是把信息送到标准错误输出流中呢?
为了验证一下,我们把输出信息重定向到文件中: head -2 /etc/passwd > 1.txt 此时发现输出信息流向了1.txt中。
之后执行 head -2 /etc/shadow > 2.txt,你会发现,怎么信息没有被重定向呢? 不是写到2.txt中才正确吗?
有了这个疑问,我们应该知道了stdout,stderr不是同一个输出流:
通过这个图我们看出,命令出错时走的是stderr,命令正常输出走的是 stdout, 所以我们 >2.txt 没有起作用,因为他只重定向标准输出流,而错误输出流并不是通过>运算符来重定向的。
(一) 标准错误输出流
同标准输出流重定向类似,标准错误输出流用2>来定义。
[cclove@localhost ~]$ head /etc/shadow 2> 2.txt
[cclove@localhost ~]$ cat 2.txt
head: cannot open ‘/etc/shadow’ for reading: Permission denied
[cclove@localhost ~]$
这回用2>把错误信息重定向到2.txt中,发现这回正确了,查看2.txt果然如此。
(二) 合并标准输出和标准错误
我们用head命令同时查看两个文件,并把查看的信息重定向到 1.txt 中,错误的信息重定向到2.txt中。 经检测一切正常,只不过写到一行了。现在我们要把这些信息都放到1.txt中.
[cclove@localhost ~]$ head -2 /etc/passwd /etc/shadow >1.txt 2>1.txt
[cclove@localhost ~]$ cat 1.txt
head: cannot open ‘/etc/shadow’ for reading: Permission denied
linux@myccloves:~$ head -2 /etc/passwd /etc/shadow >1.txt 2>1.txt
bin:/sbin/nologin
这回我们把两个信息流都重定向到1.txt中,但查看和我们想像的结果不一样。因为在重向时,需要打开文件,但同一个文件被打开两次,最终进行了互相伤害,导致文件损坏。为了防止这种事情发生,我们应该有效的结合两个输出流,合并为一个流。
这回正确了,2>&1表示,把错误流送到标准输出流中,这样就整合到一起了。 上面讨论的是老式的作法,为了简化现在用>&来实现。
linux@myccloves:~$ head -2 /etc/passwd /etc/shadow >& 1.txt
重定向总结一下:
重定向 | 说明 |
---|---|
cmd < file | 从file重定向到标准输入。 |
cmd > file | 把标准输出重向定到file中,如果file存在,覆盖。 |
cmd >> file | 把标准输出重向定到file中,如果file存在,追加。 |
cmd 2> file | 把标准错误重向定到file中,如果file存在,覆盖。 |
cmd 2>> file | 把标准错误重向定到file中,如果file存在,追加。 |
cmd > file 2>&1 | 合并标准输出和标准错误输出,并且重定向到file中 |
cmd >& file | 合并标准输出和标准错误输出,并且重定向到file中 |
三、管道
所谓管道(pipe)就是一个程序的数据输出,被管道送到另一个程序的输入,即:另一个程序读取被送来的数据。
我们一步一步理解:
linux@myccloves:~$ cat /etc/os-release
PRETTY_NAME="Deepin 15"
NAME="Deepin"
VERSION_ID="15.6"
VERSION="15.6"
ID=deepin
HOME_URL="https://www.deepin.org/"
BUG_REPORT_URL="http://feedback.deepin.org/feedback/"
我们用cat查看一个文件,发现这里的行,不是按字母表的顺序排列的。linux中有一个sort命令可以排序。
linux@myccloves:~$ sort /etc/os-release
BUG_REPORT_URL="http://feedback.deepin.org/feedback/"
HOME_URL="https://www.deepin.org/"
ID=deepin
NAME="Deepin"
PRETTY_NAME="Deepin 15"
VERSION="15.6"
VERSION_ID="15.6"
这回我们观察,这些行按字母的顺序排序了。
这两步能不能合成一步呢? 首先cat把os-release的内容输出,之后sort读取/etc/os-release的内容。一个进程输出,别一个进行需要输入,这种需求正符合管道的思想,所以合并一下:
linux@myccloves:~$ cat /etc/os-release | sort
BUG_REPORT_URL="http://feedback.deepin.org/feedback/"
HOME_URL="https://www.deepin.org/"
ID=deepin
NAME="Deepin"
PRETTY_NAME="Deepin 15"
VERSION="15.6"
VERSION_ID="15.6"
管道一般与grep组合,用于查看感兴趣的文本行,比如:我们要查看linux用户的信息
linux@myccloves:~$ cat /etc/passwd | grep linux
linux : x : 1000 : 1000 :: /home/linux : /bin/bash
grep 从管道读取传递过来的数据,之后查找有linux字样的文本行就打印出来。这个功能很常用也很强大。当然grep本身也可以读取文件进行查找,比如:
linux@myccloves:~$ grep linux /etc/passwd
linux : x : 1000 : 1000 :: /home/linux : /bin/bash
注意:管道遇到标准错误时,标准错误是不流向管道的,所以会正常输出到错误输出流中。
linux@myccloves:~$ cat /etc/shadow | grep linux
cat: /etc/shadow: Permission denied