数据流重定向(redirect)由字面上的意思来看,好像就是将【数据给它定向到其他地方去】的样子?
没错,数据流重定向就是将某个命令执行后应该要出现在屏幕上的数据,给它传输到其他的地方,例如文件或是设备(例如打印机之类的)。
这玩意儿在Linux的命令行模式下面很重要,尤其是如果我们想要将某些数据存储下来时,就更有用了。
1.什么是数据流重定向
什么是数据流重定向?这得要由命令的执行结果谈起。
一般来说,如果你要执行一个命令,通常它会是这样的:
我们执行一个命令的时候,这个命令可能会由文件读入数据,经过处理之后,再将数据输出到屏
幕上。
在上图当中,standard output 与standard error output分别代表【标准输出(STDOUT)】与【标准错误输出(STDERR)】,这两个玩意儿默认都是输出到屏幕上面来的
那么什么是标准输出与标准错误输出?
简单地说,标准输出指的是命令执行所返回的正确信息,而标准错误输出可理解为命令执行失败后,所返回的错误信息。
举个简单例子来说,
我们的系统默认有/etc/crontab但却无/etc/birdsay,此时若执行【cat /etc/crontab /etc/vbirdsay】这个命令时,cat会进行:
- 标准输出:读取/etc/crontab后,将该文件内容显示到屏幕上;
- 标准错误输出:因为无法找到/etc/vbirdsay,因此在屏幕上显示错误信息;
不管正确或错误的数据都是默认输出到屏幕上,所以屏幕当然是乱的。
那能不能通过某些机制将这两股数据分开?
当然可以,那就是数据流重定向的功能,数据流重定向可以将standard output(简称stdout)与standard error output(简称stderr)分别传送到其他的文件或设备,而分别传送所用的特殊字符则如下所示:
- 标准输入(stdin):代码为0,使用<或<<;
- 标准输出(Stdout):代码为1,使用>或>>;
- 标准错误输出(stderr):代码为2,使用2>或2>>;
2.标准输出流重定向
什么是标准输出重定向?
输出重定向:指的是重新指定设备来代替显示器作为新的输出设备。
2.1. >
cpp
[root@zaishu ~]# ls -l > x 不输出到屏幕,输出到文本,这就是输出重定向;另外当指定没有描述符的时候,默认就是标准数据流。
root@zaishu ~]# ls -l 1> x (这两条命令的效果一样 1就是代表标准输出流)
范例一:观察你的系统根目录(/)下各目录的文件名、权限与属性,并记录下来
此时屏幕会显示出文件名信息
屏幕并无任何信息
有个新文件被建立了。
我们打开看看
怪了,屏幕怎么会完全没有数据?这是因为原本【ll /】所显示的数据已经被重定向到~/rootfile文件中了,这个~/rootfile的文件名可以随便你取。
如果你执行【cat ~/rootfile】那就可以看到原本应该在屏幕上面的数据。
如果我再次执行:【ll /home > ~/rootfile】后,这个~/rootfile文件的内容变成什么呢?
它将变成【仅有ll /home的数据】而已。咦?原本的【ll /】数据就不见了吗?
是的,因为该文件的建立方式是:
- 该文件(本例中是~/rootfile)若不存在,系统会自动地将它建立起来。
- 当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入。
- 也就是若以>输出到一个已存在的文件中,这个文件就会被覆盖掉。
2.2. >>
那如果我想要将数据累加而不想要将旧的数据删除,那该如何是好?
利用两个大于的符号(>>)就好。
以上面的范例来说,你应该要改成【ll >> ~/rootfile】即可。
如此一来,当
- (1)~/rootfile不存在时系统会主动建立这个文件;
- (2)若该文件已存在,则数据会在该文件的最下方累加进去。
我们接着上面那个例子来讲讲
来总结一下
3.标准错误流重定向
上面谈到的是标准输出的正确数据,那如果是标准错误的错误数据?
那就通过2>及2>>,同样是覆盖(2>)与累加(2>>)的特性。
stdout代码是1而 stderr代码是2,所以这个2>是很容易理解的,而如果仅存在>时,则代表默认的代码1,也就是说:
- 1>:以覆盖的方法将【正确的数据】输出到指定的文件或设备上;
- 1>>:以累加的方法将【正确的数据】输出到指定的文件或设备上;
- 2>;以覆盖的方法将【错误的数据】输出到指定的文件或设备上;
- 2>>;以累加的方法将【错误的数据】输出到指定的文件或设备上;
要注意,【1>>】以及【2>>】中间是没有空格的,
OK,有些概念之后让我们继续聊一聊这家伙怎么应用吧!
当你以一般身份执行find这个命令的时候,由于权限的问题可能会产生一些错误信息
例如执行【find /home -name testing】时,可能会产生类似【find:/root:Permission denied】之类的信息,例如下面这个范例:
范例二:利用一般身份账号查找/home下面是否有名为,bashrc的文件存在.
下面还有我们之前建立的账号存在,这些账号的根目录你当然不能进入,所以就会有错误及正确数据,好了,
那么假如我想要将数据输出到 list 这个文件中?
执行【find /home -name.bashrc > list】会有什么结果?
呵呵,你会发现 list 里面存了刚刚那个【正确】的输出数据,至于屏幕上还是会有错误的信息出现,伤脑筋。
如果想要将正确的与错误的数据分别存入不同的文件中需要怎么做?范例三:承范例二,将stdout与stderr分别存到不同的文件中
注意,此时屏幕上不会出现任何信息。因为刚刚执行的结果中,有Permission 的那几行错误信息都会跑到 list_error 这个文件中,至于正确的输出数据则会存到 list_right 这个文件中。
这样可以了解了吗?如果有点混乱的话,去休息一下再回来看看吧!
4./dev/null 垃圾桶黑洞设备与特殊写法
想象一下,如果我知道错误信息会发生,所以要将错误信息忽略掉而不显示或存储?
这个时候黑洞设备/dev/nul 就很重要了,这个/dev/nul可以吃掉任何导向这个设备的信息。
将上述的范例自定义
范例四:承范例三,将错误的数据丢弃,屏幕上显示正确的数据.
只有 stdout 会显示到屏幕上,stderr 被丢弃了
再想象一下,如果我要将正确与错误数据通通写入同一个文件中?
这个时候就得要使用特殊的写法了。我们同样用下面的案例来说明:
范例五:将命令的数据全部写入名为list 的文件中
错误 ,由于两股数据同时写入一个文件,又没有使用特殊的语法,此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。
正确
正确
至于写入同一个文件的特殊语法如上表所示,你可以使用2>&1也可以使用&>
4.1.&(重点)
& 是一个描述符,如果在1和2前面不加&,这个时候1和2表示的是普通文件。加了&表示的是重定向到对应的设备。 举例:
- 1>&2 意思是把标准输出重定向到标准错误,如果是 1>2 表示的是将标准输出重定向到2这个文件。
- 2>&1 意思是把标准错误输出重定向到标准输出。如果是 2>1 表示的是将标准错误重定向到1这个文件
- &>filename 意思是把标准输出和标准错误输出都重定向到文件filename中
5.standard input :<与<<
输入重定向:指的是重新指定设备来代替键盘作为新的输入设备;
了解了stder与stdout后,那么那个<又是什么呀?
呵呵,以最简单的语法来说,那就是【将原本需要由键盘输入的数据,改由文件内容来替换】的意思。
5.1.cat
我们先由下面的cat 命令操作来了解一下什么叫做键盘输入吧!
范例六:利用cat命令来建立一个文件的简单流程。
执行后我们输入一些东西
这里按下[ctrl]+d来退出。
由于加入>在cat后,所以这个catfile会被主动地建立,而内容就是刚刚键盘上面输入的那两行数据了。
唔,那我能不能用纯文本文件替换键盘的输入,也就是说,用某个文件的内容来替换键盘的敲击?可以的,如下所示:
范例七:用stdin替换键盘的输入以建立新文件的简单流程。
注意看,这两个文件的大小会一模一样,几乎像是使用cp来复制一般。
这东西非常有帮助,尤其是用在类似mail这种命令的使用上。
理解<之后,再来则是怪可怕的<< 这个连续两个小于的符号了,它代表的是【结束的输入字符】的意思。
举例来讲:我要用cat直接将输入的信息输出到catfile中,且当由键盘输入eof时,该次输入就结束,那我可以这样做:
输入eof这关键词,立刻就结束而不需要输入[ctrl]+d。且文件里只有这两行,不会存在关键词那一行
看到了吗?利用<<右侧的控制字符,我们可以终止一次输入,而不必按下[crtl]+d来结束,这对程序写作很有帮助。
5.2.<,<<
cpp
[root@zaishu ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
saslauth:x:998:76:Saslauthd user:/run/saslauthd:/sbin/nologin
oracle:x:1002:1002::/home/oracle:/bin/bash
cpp
[root@zaishu ~]# cat < /etc/passwd //将passwd内容输给cat,cat然后将内容输出到屏幕
root:x:0:0:root:/root:/bin/bash
...
saslauth:x:998:76:Saslauthd user:/run/saslauthd:/sbin/nologin
oracle:x:1002:1002::/home/oracle:/bin/bash
例2. 分界符
cpp
[root@zaishu ~]# cat << 0 //遇到0,表示跳出
> a
> b
> c
> 0
a
b
c
例3. 输入 输出一起用
通过重定向 将/etc/passwd 作为输入设备,并输出重定向到 shu.txt,最终实现将 /etc/passwd 文件中内容复制到 shu.txt 。
cpp
[root@prometheus ~]# cat < /etc/passwd > shu.txt
[root@prometheus ~]# cat shu.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
prometheus:x:998:996::/home/prometheus:/bin/bash
node_exporter:x:997:995::/home/node_exporter:/bin/bash
6.为何要使用命令输出重定向?
好了,那么为何要使用命令输出重定向?
我们来说一说吧!
- 屏幕输出的信息很重要,而且我们需要将它存下来的时候;
- 后台执行中的程序,不希望它干扰屏幕正常的输出结果时;
- 一些系统的计划任务命令(例如写在/etc/crontab中的文件)的执行结果,希望它可以存 下来时;
- 一些执行命令的可能已知错误信息时,想以【2> /dev/null】将它丢掉时;
- 错误信息与正确信息需要分别输出时。
·当然还有很多的功能,最简单的就是网友们常常问到的:为何我的root 都会收到系统crontab传来的错误信息?
这个东西是常见的错误,而如果我们已经知道这个错误信息是可以忽略的时候,嗯,【2> errorfile】这个功能就很重要了。了解了吗?
例题
问: 假设我要将echo "error message"以标准错误的格式来输出,该如何处置?
答:
既然有2>&1来将2>转到1>去,那么应该也会有1>&2吧?没错,就是这个概念,因此你可以这样做:
- [dmtsai@study -]$ echo "error message" 1>&2
- [dmtsai@study -]$ echo "error message" 2> /dev/null 1>&2
你会发现第一条有信息输出到屏幕上,第二条则没有信息,这表示该信息已经通过2>/dev/null丢到垃圾桶中了,可以肯定是错误信息。