linux标准输入输出

576 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

一、什么是输入输出

标准输入0 从键盘获得输入 /proc/self/fd/0
标准输出1 输出到屏幕(即控制台) /proc/self/fd/1
错误输出2 输出到屏幕(即控制台) /proc/self/fd/2

上图中,键盘为标准输入也就编号为0,而标准输出1和标准错误2默认都是在终端显示。
运行一个程序时 , 需要从某个位置读取输入信息 , 然后 cpu 处理, 最后将输出显示到屏幕或文件进程通过文件描述符的编号通道来获取输入并输出。

序号名称描述默认连接用法
0stdin标准输入键盘仅读取
1stdout标准输出显示器仅写入
2stderr错误输出显示器仅写入

二、管理输入输出

1、重定向输入

不再使用键盘作为标准输入,使用指定文件作为标准输入设备。输入重定向包括两种类型:

序号类型格式功能
1重定向标准输入命令 <文件命令把文件的内容作为标准输入
2标识符限定输入命令<<标识符命令把标准输入的内容输出到文件,直到遇到“标识符”为止

(1)重定向标准输入

如下脚本所示,先创建一个文件

#创建a.txt
[root@o7lhevly3ppn9xix ~]# ls -l >a.txt
#使用awk 打印a.txt第一列内容,a.txt做为标准输入
[root@o7lhevly3ppn9xix ~]# awk '{print $1}'< a.txt
total
-rw-r--r--
-rw-r--r--
-rw-r--r--
-rw-r--r--
-rw-r--r--
-rw-r--r--
drwxr-xr-x
drwxr-xr-x

(2)标识符限定输入

EOF是END Of File的缩写,表示自定义终止符.既然自定义,那么EOF就不是固定的,可以随意设置别名。

如下脚本所示,向a.txt写入内容,遇到EOF结束

[root@o7lhevly3ppn9xix ~]# cat  << EOF >a.txt
> aa
> bb
> cc
> dd
> EOF
[root@o7lhevly3ppn9xix ~]# cat a.txt 
aa
bb
cc
dd

2、重定向输出

经常使用的场景是把原本输出到屏幕的信息,重定向输出到文件,比如项目的日志信息。重定向命令如下:

序号重定向命令含义
11>重定向正确输出
22>重定向错误输出
3&>重定向所有输出
42>&1对于2>&1的理解,2就是标准错误输出,1是标准正确输出,那么这条命令不就是相当于把标准错误重定向到标准输出么?是的。为什么是&1而不是1,这里& 符号是什么?& 符号可以理解为引用(reference)。&1 就是对标准输出的引用。
5>>追加重定向正确输出
62>>追加重定向错误输出
7&>>追加重定向所有输出

例如,如下代码,往date.txt中写入时间。重定向会覆盖源文件内容,如果需要向文件内追加内容需要把重定向的>符号改为>>即可。

[root@o7lhevly3ppn9xix ~]# date >date.txt
[root@o7lhevly3ppn9xix ~]# cat date.txt 
Thu Nov 18 15:34:28 CST 2021

编写test.sh,如下所示,启动t命令并不存在,执行会报错,错误信息会输出到stderr,date能正常执行,输出当前时间到stdout。

[root@o7lhevly3ppn9xix ~]# ./test.sh 
./test.sh: line 2: t: command not found
Thu Nov 18 15:41:03 CST 2021

linux命令行的 2>&1 究竟是什么意思?

执行以下命令,标准输出重定向到test.log中,错误输出依然在stderr中

#错误输出依然在stderr中
[root@o7lhevly3ppn9xix ~]# ./test.sh >test.log
./test.sh: line 2: t: command not found

执行以下命令,标准输出,错误输出都重定向到test.log

[root@o7lhevly3ppn9xix ~]# ./test.sh > test.log 2>&1
[root@o7lhevly3ppn9xix ~]# cat test.log 
./test.sh: line 2: t: command not found
Thu Nov 18 15:46:58 CST 2021

或者执行以下命令达到相同的效果。

[root@o7lhevly3ppn9xix ~]# ./test.sh &> test.log

command 1>a 2>&1与command 1>a 2>a 还是有区别的,区别就在于前者只打开一次文件a,后者会打开文件两次,并导致stdout被stderr覆盖。&1的含义就可以理解为用标准输出的引用,引用的就是重定向标准输出产生打开的a。从IO效率上来讲,command 1>a 2>&1比 command 1>a 2>a的效率更高。