Linux的IO输入输出有三类

  • Standard Input 代码 0      #标准输入:从键盘输入,即从键盘读入数据。

  • Standard Output 代码 1    #标准输出:把数据输出到终端上。

  • Standard Error 代码 2       #标准输出:把数据输出到终端上。

默认的标准输入指的是键盘,默认的标准输出与标准错误输出是屏幕或者是终端。

系统为这三个文件分配了文件标识符fd(file descripter).分别为0,1,2.

在Linux系统下,一切皆是文件,对文件的操作,一般要用到文件标识符。

在计划任务中经常可以看到。例如我们公司的计划任务举例:

*/2 * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testOne >/dev/null 2>&1
*/2 * * * * root cd /opt/xxxx/test_S1/html/xxxx/admin; php index.php task testTwo >/dev/null 2>&1

对于& 1 更准确的说应该是文件描述符 1,而1表示标准输出,stdout。

对于2 ,表示标准错误,stderr。

2>&1 的意思就是将标准错误重定向到标准输出。这里标准输出已经重定向到了 /dev/null。那么标准错误也会输出到/dev/null

可以把/dev/null 可以看作"黑洞". 它等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到.

偶尔也可以把 & 在命令的最后加上,表示让程序后台执行。

为何2>&1要写在后面?

index.php task testOne >/dev/null 2>&1

我们可以理解为,左边是标准输出,好,现在标准输出直接输入到 /dev/null 中,而2>&1是将标准错误重定向到标准输出,所以当程序产生错误的时候,相当于错误流向左边,而左边依旧是输入到/dev/null中。

PS:

command > file 2>file 与command > file 2>&1 是不同的:

command > file 2>file :是将命令所产生的标准输出信息stdout和错误的输出信息stderr送到file中,但这样会导致file会被打开两次,所以stdout和stderr会互相覆盖。实际上FD1和FD2同时使用file,引起资源竞争。

command >file 2>&1:将stdout直接送向file,而stderr是继承FD1管道后被送往file,所以file 只被打开一次,stdout和stderr共用FD1一个管道。实际相当于stderr合并到stdout后一起输出到file中。

  • 从IO效率上,前一条命令的效率要比后面一条的命令效率要低.

  • 标准输出与错误输出同时输出:command  2>file 1>file 会因抢占file文件的管道二出现乱码/确实/覆盖等现象(即两个输出流操作一个文件的写入).

  • 所以在编写shell脚本的时候,较多的时候我们会用command > file 2>&1 这样的写法

区别:command >/dev/null 2>&1 与command  2>&1 >/dev/null

  • 前者先将标准输出输出到/dev/null中,再将错误输出重定向到标准输出,所以都输出到/dev/null

  • 后者先将错误输出重定向到标准输出也就是输出到屏幕上,再将标准输出到/dev/null,只是把原来的标准输出输出到/de/null中,错误输出重定向到标准输出会显示在屏幕上;