文章目录
欢迎访问个人网络日志🌹🌹知行空间🌹🌹
Linux Shell输入输出流管理
目前对于普通用户来说,接触到最多的Linux Shell
输出的方法有两个,一个是显示到显示器上,一个是将输出重定向到文件中。不过,目前的方式,只能二选一,要么将shell
全部输出到显示器上,要么将shell
输出全部保存到文件中,如果想将一部分输出到显示上一部分记录到文件中,那么该如何实现呢?如何用标准的Linux
输入和输出系统来将脚本输出导向特定位置呢?
1)标准文件描述符
Linux
系统将每个对象当作文件处理。Linux
用文件描述符来标识每个文件对象。文件描述符是一个非负整数,可以唯一标识会话中打开的文件。每个进程一次最多可以有九个文件描述符。出于特殊目的,bash shell
保留了前三个文件描述符(0, 1, 2)
。这三个特殊文件描述符作为标准的文件描述符会处理脚本的输入和输出。
文件描述符 | 缩写 | 描述 |
---|---|---|
0 | STDIN | 标准输入 |
1 | STDOUT | 标准输出 |
2 | STDERR | 标准错误 |
STDIN
文件描述符代表shell
的标准输入。对终端界面来说,标准输入是键盘。shell
从 STDIN
文件描述符对应的键盘获得输入,在用户输入时处理每个字符。
许多bash
命令能接受 STDIN
的输入,尤其是没有在命令行上指定文件的话。
当在命令行上只输入 cat
命令时,它会从 STDIN
接受输入。输入一行, cat
命令就会显示出一行。
$ cat
this is a line
this is a line
在使用输入重定向符号( < )
时,Linux
会用重定向指定的文件来替换标准输入文件描述符。它会读取文件并提取数据,就如同它是键盘上键入的。
可以通过 STDIN
重定向符号强制 cat
命令接受来自另一个非 STDIN
文件的输入:
cat < file
this is a line
**STDOUT文件描述符代表shell
的标准输出。**在终端界面上,标准输出就是终端显示器。shell
的所有输出(包括shell
中运行的程序和脚本)会被定向到标准输出中,也就是显示器。
通过输出重定向符号,通常会显示到显示器的所有输出会被shell
重定向到指定的重定向文件。
$ ls -alh > test.log
# cat test.log
# 总用量 12K
# drwxrwxr-x 2 rob rob 4.0K 1月 5 23:28 .
# drwxr-xr-x 6 rob rob 4.0K 1月 5 23:28 ..
# -rw-rw-r-- 1 rob rob 3 1月 5 23:28 1.txt
# -rw-rw-r-- 1 rob rob 0 1月 5 23:28 test.log
也可以用>>
符号将数据追加到某个文件。
$ who >> test.log
# cat test.log
# 总用量 12K
# drwxrwxr-x 2 rob rob 4.0K 1月 5 23:28 .
# drwxr-xr-x 6 rob rob 4.0K 1月 5 23:28 ..
# -rw-rw-r-- 1 rob rob 3 1月 5 23:28 1.txt
# -rw-rw-r-- 1 rob rob 0 1月 5 23:28 test.log
# lx :1 2024-01-02 21:11 (:1)
当命令生成错误消息时,shell
并不能将错误消息重定向到输出重定向文件。
$ ls -alh rob > test.log
# ls: 无法访问 'rob': 没有那个文件或目录
test.log
文件创建成功了,只是里面是空的。shell
对于错误消息的处理是跟普通输出分开的。
STDERR文件描述符用来处理错误消息。STDERR
文件描述符代表shell
的标准错误输出。shell
或shell
中运行的程序和脚本出错时生成的错误消息都会发送到这个位置。
尽管分配给它们的文件描述符值不同,默认情况下, STDERR
文件描述符会和 STDOUT
文件描述符指向同样的地方,譬如显示器,但STDERR
并不会随着 STDOUT
的重定向而发生改变。
要重定向错误输出,只需要在使用重定向符号时定义 STDERR
文件描述符就可以了。STDERR
文件描述符被设成 2
,可以选择只重定向错误消息。
$ ls -al rob 2> test.log
cat test.log
# ls: 无法访问 'rob': 没有那个文件或目录
用这种方法,shell
会只重定向错误消息,正常 STDOUT
输出仍然会发送到默认的 STDOUT
文件描述符,也就是显示器。
要同时重定向错误和正常输出,必须用两个重定向符号。
$ ls -al rob test.log 2> test.log 1>out.log
cat test.log