1. 理解输入和输出
1.1 标准文件描述符
Linux 系统将每个对象当作文件处理。这包括输入和输出进程。Linux 用文件描述符(file descriptor)来标识每个文件对象。文件描述符是一个非负整数,可以唯一标识会话中打开的文件。每个进程一次最多可以有九个文件描述符。Linux 标准文件描述符如下:
STDIN
STDIN 文件描述符代表 shell 的标准输入。对终端界面来说,标准输入是键盘。shell 从 STDIN 文件描述符对应的键盘获得输入,在用户输入时处理每个字符。
在使用输入重定向符号(<)时,Linux 会用重定向指定的文件来替换标准输入文件描述符。它会读取文件并提取数据,就如同它是键盘上键入的。
可以通过 STDIN 重定向符号强制 cat 命令接受来自另一个非 STDIN 文件的输入。
$ cat < testfileThis is the first line.This is the second line.This is the third line.$
现在 cat 命令会用 testfile 文件中的行作为输入。
STDOUT
STDOUT 文件描述符代表 shell 的标准输出。在终端界面上,标准输出就是终端显示器。shell 的所有输出(包括 shell 中运行的程序和脚本)会被定向到标准输出中,也就是显示器。
$ ls -l > test2$ cat test2total 20-rw-rw-r-- 1 rich rich 53 -10-16 11:30 test-rw-rw-r-- 1 rich rich 0 -10-16 11:32 test2-rw-rw-r-- 1 rich rich 73 -10-16 11:23 testfile$
通过输出重定向符号,通常会显示到显示器的所有输出会被 shell 重定向到指定的重定向文件。
可以将数据追加到某个文件。这可以用>>符号来完成。
$ who >> test2$ cat test2total 20-rw-rw-r-- 1 rich rich 53 -10-16 11:30 test-rw-rw-r-- 1 rich rich 0 -10-16 11:32 test2-rw-rw-r-- 1 rich rich 73 -10-16 11:23 testfilerich pts/0 -10-17 15:34 (192.168.1.2)$
shell 对于错误消息的处理是跟普通输出分开的。
$ ls -al badfile > test3ls: cannot access badfile: No such file or directory$ cat test3$
STDERR
shell 通过特殊的 STDERR 文件描述符来处理错误消息。STDERR 文件描述符代表 shell 的标准错误输出。shell 或 shell 中运行的程序和脚本出错时生成的错误消息都会发送到这个位置。
默认情况下,STDERR 文件描述符会和 STDOUT 文件描述符指向同样的地方(尽管分配给它们的文件描述符值不同)。也就是说,默认情况下,错误消息也会输出到显示器输出中。
但如上例,STDERR 并不会随着 STDOUT 的重定向而发生改变。
1.2 重定向错误
只重定向错误
STDERR 文件描述符被设成 2。可以选择只重定向错误消息,将该文件描述符值放在重定向符号前。该值必须紧紧地放在重定向符号前,否则不会工作。
$ ls -al badfile 2> test4$ cat test4ls: cannot access badfile: No such file or directory$
重定向错误和数据
如果想重定向错误和正常输出,必须用两个重定向符号。需要在符号前面放上待重定向数据所对应的文件描述符,然后指向用于保存数据的输出文件。
$ ls -al test test2 test3 badtest 2> test6 1> test7$ cat test6ls: cannot access test: No such file or directoryls: cannot access badtest: No such file or directory$ cat test7-rw-rw-r-- 1 rich rich 158 -10-16 11:32 test2-rw-rw-r-- 1 rich rich 0 -10-16 11:33 test3$
shell 利用 1> 符号将 ls 命令的正常输出重定向到了 test7 文件,而这些输出本该是进入 STDOUT 的。所有本该输出到 STDERR 的错误消息通过 2> 符号被重定向到了 test6 文件。
也可以将 STDERR 和 STDOUT 的输出重定向到同一个输出文件。为此 bash shell 提供了特殊的重定向符号 &>。
$ ls -al test test2 test3 badtest &> test7$ cat test7ls: cannot access test: No such file or directoryls: cannot access badtest: No such file or directory-rw-rw-r-- 1 rich rich 158 -10-16 11:32 test2-rw-rw-r-- 1 rich rich 0 -10-16 11:33 test3$
当使用 &> 符时,命令生成的所有输出都会发送到同一位置,包括数据和错误。
2. 在脚本中重定向输出
2.1 临时重定向
在重定向到文件描述符时,你必须在文件描述符数字之前加一个 &:
echo "This is an error message" >&2
这行会在脚本的 STDERR 文件描述符所指向的位置显示文本,而不是通常的 STDOUT。
$ cat test8#!/bin/bash# testing STDERR messagesecho "This is an error" >&2echo "This is normal output"$
像平常一样运行这个脚本,你可能看不出什么区别。
$ ./test8This is an errorThis is normal output$
默认情况下,Linux 会将 STDERR 导向 STDOUT。但是,如果你在运行脚本时重定向了STDERR,脚本中所有导向 STDERR 的文本都会被重定向。
$ ./test8 2> test9This is normal output$ cat test9This is an error$
2.2 永久重定向
如果脚本中有大量数据需要重定向,那重定向每个 echo 语句就会很烦琐。取而代之,你可以用exec 命令告诉 shell 在脚本执行期间重定向某个特定文件描述符。
$ cat test10#!/bin/bash# redirecting all output to a fileexec 1>testoutecho "This is a test of redirecting all output"echo "from a script to another file."echo "without having to redirect every individual line"$ ./test10$ cat testoutThis is a test of redirecting all outputfrom a script to another file.without having to redirect every individual line$
exec 命令会启动一个新 shell 并将 STDOUT 文件描述符重定向到文件。脚本中发给 STDOUT 的所有输出会被重定向到文件。
$ cat test11#!/bin/bash# redirecting output to different locationsexec 2>testerrorecho "This is the start of the script"echo "now redirecting all output to another location"exec 1>testoutecho "This output should go to the testout file"echo "but this should go to the testerror file" >&2$$ ./test11This is the start of the scriptnow redirecting all output to another location$ cat testoutThis output should go to the testout file$ cat testerrorbut this should go to the testerror file$
2.3 在脚本中重定向输入
exec 命令允许你将 STDIN 重定向到Linux 系统上的文件中:exec 0< testfile
$ cat test12#!/bin/bash# redirecting file inputexec 0< testfilecount=1while read linedoecho "Line #$count: $line"count=$[ $count + 1 ]done$ ./test12Line #1: This is the first line.Line #2: This is the second line.Line #3: This is the third line.$
4. 创建自己的重定向
待补充
5. 阻止命令输出
可以将 STDERR 重定向到一个叫作 null 文件的特殊文件。null 文件跟它的名字很像,文件里什么都没有。shell 输出到 null 文件的任何数据都不会保存,全部都被丢掉了。
在 Linux 系统上 null 文件的标准位置是 /dev/null。你重定向到该位置的任何数据都会被丢掉,不会显示。
$ ls -al > /dev/null$ cat /dev/null$
也可以在输入重定向中将 /dev/null 作为输入文件。由于 /dev/null 文件不含有任何内容,程序员通常用它来快速清除现有文件中的数据,而不用先删除文件再重新创建。
$ cat testfileThis is the first line.This is the second line.This is the third line.$ cat /dev/null > testfile$ cat testfile$
Linux shell 学习笔记(11)— 理解输入和输出(标准输入 输出 错误以及临时重定向和永久重定向)