关于 command > /dev/null 2>&1
程序会处理外部的输入,然后将运算的结果输出到指定的位置。常见的后台运行的程序,输入可能来自于外部的文件,运算的结果也写入到其他文件中。
在交互式程序里(比如和Linux交互的bash),输入通常都是用户的键盘和鼠标,输出则是用户的屏幕。当然也会有将输出的结果存储到文件中的需求,例如,从几个G的log文件中删选感兴趣的部分,这个时候就会用到输入输出的重定向。
文件描述符-FD
在Linux的环境下,一切皆文件。通过文件可以访问常规数据、网络链接、I/O设备等。对应的,当程序在使用某个文件的时候,系统都会为程序分配一个文件描述符,无论这个文件的本质如何,该文件描述符为程序和操作系统之间的交互提供了通用接口。每个程序都至少会这三个文件描述符:0、1、2;
在通过命令和Linux交互的时候,就是让/bin/bash程序来解释执行shell脚本,这个程序使用的文件描述符如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xuJm58aZ-1638956415681)(/home/idriver/.config/Typora/typora-user-images/image-20211207151644687.png)]
其中,上面提到的0、1、2分别是:
文件描述符 | 类型 | 默认位置 | 打开文件的确切名称 |
---|---|---|---|
0 | 标准输入 | 用户设备(键盘) | /dev/pts/30 |
1 | 标准输出 | 屏幕 | /dev/pts/30 |
2 | 错误输出 | 屏幕 | /dev/pts/30 |
截图中0、1、2后面的u表示文件状态模式
- u:表示该文件被打开且处于读取/写入模式;
- r:表示该文件被打开且处于只读模式;
- w:表示该文件被打开且处于写入模式;
- -:表示该文件的状态模式未知,且被锁定;
- 空格:表示该文件的状态模式未知,且未被锁定;
重定向
通常使用>
或者>>
进行输出重定向,符合左边为文件描述符(默认为1),右边是一个文件(当然也可以是一个输出设备);使用<
重定向输入,左边为文件描述符(默认为0)。
输出重定向
当前目录结果如下:
# ll
total 8
-rw-r--r-- 1 root root 6 12月 7 17:33 out.txt
-rw-r--r-- 1 root root 4 12月 7 17:33 out1.txt
command >filename->把标准输出重定向到文件中,也可写作command 1>filename
;
# ls out.txt test.txt
ls: cannot access test.txt: No such file or directory
out.txt
#将标准输出重定向到newfile文件中,此时错误输出依旧输出在控制台。
# ls out.txt test.txt > newfile
ls: cannot access test.txt: No such file or directory
# cat newfile
out.txt
command >>filename->把标准输出重定向追加到文件中,也可写作command 1>>filename
;
#将标准输出重定向到newfile文件中,此时发现上一步中输出到文件中的内容被覆盖掉了。
# ls out1.txt test.txt > newfile
ls: cannot access test.txt: No such file or directory
# cat newfile
out1.txt
#将标准输出重定向追加到newfile文件中,此时发现上一步中输出到文件中的内容依旧存在。
# ls out.txt test.txt >> newfile
ls: cannot access test.txt: No such file or directory
# cat newfile
out1.txt
out.txt
command 2>filename->把标准错误输出重定向到文件中;
#将标准错误输出重定向到errfile文件中。
# ls out.txt test.txt 2> errfile
out.txt
# cat errfile
ls: cannot access test.txt: No such file or directory
command 2>>filename->把标准错误输出重定向追加到文件中;
#将标准错误输出追加到errfile文件中。
# ls out.txt test123.txt 2>> errfile
out.txt
]# cat errfile
ls: cannot access test.txt: No such file or directory
ls: cannot access test123.txt: No such file or directory
上述的例子中,ls out.txt test.txt
之后有两种输出,其中out.txt
为标准输出,而ls: cannot access test.txt: No such file or director
为标准错误输出。当然也可以选中将错误输出和标准输出重定向到不同的文件中。
# ls out.txt test123.txt 2>errfile >newfile
# cat newfile
out.txt
# cat errfile
ls: cannot access test123.txt: No such file or directory
输入重定向
#两个文件的内容如下:
# cat out.txt
out
# cat out1.txt
out1
command <filename ->以文件filename的内容作为命令command的标准输入。也可写作command 0<filename
;
#cat命令后面没有文件的话就会从标准输入读取数据并且从标准输出输出到屏幕上。用Ctrl+c结束。
# cat
1 2 3 4 5
1 2 3 4 5
a b c d e
a b c d e
^C
#将cat的标准输入重定向为out.txt,然后将标准输出重定向到newfile。
# cat <out.txt >newfile
# cat newfile
out
command << delimiter->从标准输入读取,遇到delimiter分隔符结束读取;
#敲入end之后,cat命令就结束了。
# cat <</
> 1 2 3 4 5
> 5 4 3 2 1
> /
1 2 3 4 5
5 4 3 2 1
重定向绑定
有了以上的基础,回头来看command > /dev/null 2>&1。
其中>/deve/null
是将command的标准输出重定向到/dev/null。在Linux系统中,写到/dev/null中的东西都会丢失,所以/dev/null也被叫做"黑洞"。2>&1
是错误输出将和标准输出同用一个文件描述符,也就是把标准错误输出和标准输出输出到同一个地方。
至此,command > /dev/null 2>&1的含义就清楚了,就是将command的标准输出和标准错误输出都丢弃掉,即不输出到控制台,也不输出到任何文件中。
如果先进行绑定,再将标准输出重定向到/dev/null。2>&1 >/dev/null这样的结果就变成了,错误输出输出到屏幕上,标准输出丢弃掉。因为在绑定的时候标准输出指向控制台输出,所以错误输出也就指向了控制台,然后把标准输出指向了/dev/null。
如果不进行绑定,将标准输出和错误输出都重定向到/dev/null。1>/dev/null 2>/dev/null,这样,标准输出和错误输出会抢占管道,所以可能会导致输出内容的时候出现缺失、覆盖、乱码等情况。采用这种写法,最后的情况是无法预估的。而且,由于文件被打开了两次,两个文件描述符会抢占性的往文件中输出内容,所以整体IO效率不如>/dev/null 2>&1来得高。