文章目录
- 数据流重定向
- 什么是数据流重定向
- 标准输出(>,>>)与标准错误输出(2>,2>>)
- /dev/null垃圾桶黑洞设备与特殊写法
- 标准输入:<与<<
- 为什么要使用命令输出重定向呢?
- 案例
数据流重定向
数据流重定向由字面意思来看,好像就是将【数据给他定向到其他地方去】的样子?没错数据流重定向就是将某个命令执行后应该要出现在屏幕上的数据,给他传输到其他地方。
什么是数据流重定向
什么是数据流重定向呢?这得由命令的执行说起,一般来说,如果你要执行一个命令,通常它会是这样的:
我们执行一个命令的时候,这个命令可能会由文件读入数据,经过处理之后,再将数据输出到屏幕上。
标准输出(>,>>)与标准错误输出(2>,2>>)
简单来说,标准输出指的是命令执行所返回的正确信息,而标准错误输出可理解为命令执行失败后,所返回的错误信息。举例来说,我们系统默认有 /etc/crontab 但却无 /etc/ajkdadjajdaj,此时若执行【cat /etc/crontab /etc/ajkdadjajdaj】这个命令时,cat会进行:
- 标准输出:读取/etc/crontab后,将该文件内容显示到屏幕上
- 标准错误输出:因为无法找到 /etc/ajkdadjajdaj ,因此在屏幕上显示错误信息
不管正确或错误的数据都是默认输出到屏幕上的,所以屏幕会很乱。那能不能通过某些机制将两股数据分开?那就是数据流重定向的功能,数据流重定向可以将STDOUT(标准输出)与STDEER(标准错误输出)分别传送到其他文件或设备,而分别传送所使用的特殊字符如下:
- 标准输入(STDIN):代码为0,使用<或<<
- 标准输出(STDOUT):代码为1,使用>或>>
- 标准错误输出(STDEER):代码为2,使用2>或2>>
为了理解STDOUT和STDEER,我们可以先来进行一个案例练习:
[root@localhost ~]# ll / # 屏幕会显示出文件名的信息
[root@localhost ~]# ll / > ~/rootfile # 屏幕并无信息
[root@localhost ~]# ll ~/rootfile # 新文件被建立了
-rw-r--r--. 1 root root 1014 4月 25 09:34 /root/rootfile
屏幕为什么不会输出信息呢?这是因为原本【ll /】所显示的数据已经被重定向到 ~/rootfile 文件中了,这个~/rootfile的文件名可以随便取。当你执行【cat ~/rootfile】那就可以看到原本应该在屏幕上面的数据。
[root@localhost ~]# cat ~/rootfile
总用量 20
lrwxrwxrwx. 1 root root 7 4月 5 20:07 bin -> usr/bin
dr-xr-xr-x. 5 root root 4096 4月 20 11:03 boot
drwxr-xr-x. 20 root root 3260 4月 25 09:07 dev
drwxr-xr-x. 76 root root 8192 4月 25 09:07 etc
drwxr-xr-x. 2 root root 6 4月 11 2018 home
lrwxrwxrwx. 1 root root 7 4月 5 20:07 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 4月 5 20:07 lib64 -> usr/lib64
drwxr-xr-x. 2 root root 6 4月 11 2018 media
drwxr-xr-x. 2 root root 6 4月 11 2018 mnt
drwxr-xr-x. 2 root root 6 4月 11 2018 opt
dr-xr-xr-x. 180 root root 0 4月 25 09:07 proc
dr-xr-x---. 4 root root 221 4月 25 09:34 root
drwxr-xr-x. 26 root root 780 4月 25 09:07 run
lrwxrwxrwx. 1 root root 8 4月 5 20:07 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 4月 11 2018 srv
dr-xr-xr-x. 13 root root 0 4月 25 09:07 sys
drwxrwxrwt. 16 root root 4096 4月 25 09:07 tmp
drwxr-xr-x. 13 root root 155 4月 5 20:07 usr
drwxr-xr-x. 19 root root 267 4月 5 20:14 var
如果我再次执行【ll /home > /rootfile】后,这个/root/file 文件的内容会变成什么样呢?
[root@localhost ~]# ll /home/ > ~/rootfile
[root@localhost ~]# cat ~/rootfile
总用量 0
drwx------. 2 csq csq 62 4月 25 09:52 csq
drwx------. 2 zhw zhw 62 4月 25 09:52 zhw
drwx------. 2 zzh zzh 62 4月 25 09:52 zzh
他变成【仅有 ll /home】的数据了,这是为什么呢?原本的【ll / 】 的数据不见了,这是因为文件的建立方式是:
该文件(~/rootfile)若不存在,系统会自动地将它建立起来
当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入
也就是若以>输出到一个已存在的文件中,这个文件就会被覆盖掉
那么如果我想要将数据累加而不想要将旧的数据删除,应该怎么做?利用两个大于的符号(>>)就好了。以上吗的案例来说,你应该要改成【ll / >> ~/roofile】 即可。如此一来,当~/rootfile不存在系统会主动建立这个文件,若该文件存在,则数据会在该文件的最下面累加进去。
那如果是标准错误的错误数据呢?那就通过2>及2>>,同样是覆盖(2>)与累加(2>>)的特性。刚刚上面说到stdout代码是1,而stderr代码是2,所以这个2>是很容易理解的,如果仅存在>时,则代表默认代码1,也就是说:
- 1>:以覆盖的方法将【正确的数据】输出到指定文件或设备上
- 1>>:以累加的方法将【正确的数据】输出到指定文件或设备上
- 2>:以覆盖的方法将【错误的数据】输出到指定的文件或设备上
- 2>>:以累加的方法将【错误的数据】输出到指定的文件或设备上
要注意【1>>】以及【2>>】中间是没有空格的
了解完概念再看看怎么使用,当你以一般身份执行find这个命令时,由于权限的问题可能会产生一些错误信息,例如执行【find / -name testing】时,可能会产生类似【find:/root:Permission denied】之类的信息,例如下面这个案例:
[csq@localhost ~]$ find /home -name .bashrc # 我此时的身份是csq这个一般用户
/home/csq/.bashrc <== 可以访问自己的目录下面的.bashrc文件
find: ‘/home/zhw’: Permission denied <== 报错没有权限访问
find: ‘/home/zzh’: Permission denied <== 报错没有权限访问
由于/home下面还有我们建立的其他账号存在,这些账号的根目录你当然不能进入,所以就会有错误及正确数据。
那么假如我想要将数据输出到 list 这个文件中呢?执行【find /home -name .bashrc > list】会有什么结果呢?
[csq@localhost ~]$ find /home -name .bashrc > list
find: ‘/home/zhw’: Permission denied
find: ‘/home/zzh’: Permission denied
[csq@localhost ~]$ cat list
/home/csq/.bashrc
你会发现list里面只存了刚刚的那个【正确】的输出数据。
如果我想要将正确的与错误的数据分别存入不同的文件中需要怎么做呢?
[csq@localhost ~]$ find /home -name .bashrc > list_right 2> list_error
[csq@localhost ~]$ cat list_right
/home/csq/.bashrc
[csq@localhost ~]$ cat list_error
find: ‘/home/zhw’: Permission denied
find: ‘/home/zzh’: Permission denied
你可以看到屏幕上不会出现任何信息,因为刚刚执行的结果中,有Permission denied错误的信息都会跑到【list_error】这个文件中,至于正确的信息则会存在【list_right】文件中。Do you understand?
/dev/null垃圾桶黑洞设备与特殊写法
你可以想象以下,如果我知道会有错误信息的发生,所以要将错误信息忽略掉不显示或存储应该怎么办?这个时候黑洞设备/dev/null 就很重要了,这个/dev/null 可以吃掉任何导向这个设备的信息。用法如下:
[csq@localhost ~]$ find /home -name .bashrc 2> /dev/null
/home/csq/.bashrc
# 将错误的数据丢弃,屏幕上会显示正确的数据
如果我想要将正确的数据与错误的数据通通都写入一个文件中应该怎么做?这个时候就得使用特殊的写法了,如下案例
[csq@localhost ~]$ find /home -name .bashrc > list 2>list # 错误的写法
[csq@localhost ~]$ cat list
find: ‘/home/zhw’: Permission denied
find: ‘/home/zzh’: Permission denied # 只会显示错误的数据,不会显示正确的数据
[csq@localhost ~]$ find /home -name .bashrc > list 2>&1 # 正确的写法
[csq@localhost ~]$ cat list
/home/csq/.bashrc
find: ‘/home/zhw’: Permission denied
find: ‘/home/zzh’: Permission denied # 正确的数据和错误的数据都显示了
[csq@localhost ~]$ find /home -name .bashrc &>list # 正确的写法
[csq@localhost ~]$ cat list
/home/csq/.bashrc
find: ‘/home/zhw’: Permission denied
find: ‘/home/zzh’: Permission denied # 正确的数据和错误的数据都显示了
上述案例中,第一种写法错误的原因是,有两股数据同时写入一个文件,又没有特殊的语法,此时两股数据可能会交叉写入该文件内,造成次序错乱
。上述案例中有两种写法,可以选择第二种写法最为常用
标准输入:<与<<
了解完标准输出和标准错误输出后,那么这个<与<<又是什么呢?以最简单的语法来说,那就是【将原本需要由键盘输入的数据,改由文件内容来替换】的意思
。我们先由下面的cat命令操作了解一下什么叫做键盘输入吧
案例:利用cat命令来建立一个文件的简单流程
[csq@localhost ~]$ cat > catfile
I like Linux
but I don't like English
<== 这里按下ctrl + d 来退出
[csq@localhost ~]$ cat catfile
I like Linux
but I don't like Englisht
由于加入> 在cat后,所以这个catfile会被主动地建立,而内容就是刚刚键盘上面输入的那两行数据了。那我能不能用纯文本替换键盘输入,也就是说,用某个文件的内容来替换键盘的输入
案例:用stdin替换键盘的输入以建立新文件的简单流程
[csq@localhost ~]$ cat > catfile < ~/.bashrc
[csq@localhost ~]$ ll catfile ~/.bashrc
-rw-rw-r--. 1 csq csq 231 Apr 25 15:13 catfile
-rw-r--r--. 1 csq csq 231 Apr 1 2020 /home/csq/.bashrc
# 可以看到两个文件大小一模一样,可以自行查看一下内容也是一模一样的
了解了<之后,那么<<是什么呢?它代表的是【结束的输入字符】的意思。
举例来说:我要用cat直接将输入的信息输出到catfile种,且当由键盘输入eof时,该次输入就结束
[csq@localhost ~]$ cat > catfile << "eof"
> I like Linux
> I dont like 银阁里希
> eof
[csq@localhost ~]$ cat catfile
I like Linux
I dont like 银阁里希 # 只有这两行没有关键词eof的那一行
为什么要使用命令输出重定向呢?
- 屏幕输出的信息很重要,而且我们需要将他存下来的时候
- 后台执行的程序,不希望它干扰屏幕正常的输出结果时
- 一些系统的计划任务命令(例如写在/etc/crontab 中的文件)的执行结果,希望它可以存下来时
- 一些执行命令的可能已知错误信息时,想以【2> /dev/null】将它丢掉
- 错误信息与正确信息需要分别输出时。
还有root都会收到系统crontab传来的错误信息?这个东西是常见的错误,而如果我们已经知道这个错误信息是可以忽略的时候,可以使用【2> errorfile】这个功能就很重要了。
案例
假设我要将echo "error message"以标准错误的格式来输出,该如何处置?
既然有2>&1来将2>转到1>去,那么应该会有1>&2吧,因此你可以这样做
[csq@localhost ~]$ echo "error message" 1>&2
error message
[csq@localhost ~]$ echo "error message" 2> /dev/null 1>&2
第一行中有信息输入到屏幕上,第二条则没有信息,这表示信息已经通过2> /dev/null丢掉了垃圾桶中了,可以肯定的是错误信息