重温一下Linux中关于文件描述符与重定向的相关知识。
文件描述符和重定向
1.1 相关知识
1.1.1标准输入输出,标准错误
执行一个 Shell 命令时通常会自动打开三个标准文件,分别为标准输入(stdin),标准输出(stdout),标准错误(stderr)。stdin 通常对应终端键盘,stdout,stderr 对应终端屏幕。它们三者的关系为,进程从标准输入文件中得到输入数据,将正常输出到标准输出文件,而错误信息则被送入标准错误文件中。
1.1.2 文件描述符
内核又是怎么区分这些文件的?答案是文件描述符。文件描述符是非负数。当打开现存文件或新建文件时都会返回一个文件描述符。读写文件时也需要通过文件描述符来指定待读的文件。其中,文件描述符 0,1 以及 2为系统预留的。
0 -- 标准输入(stdin)
1-- 标准输出(stdoutT)
2 -- 标准错误(stderr)
写脚本时会经 常接触到标准输入输出以及标准错误问题。正确处理这些内容能够大大减少日常工作以及便于排查错误。我们可以通过重定向到对应文件上的方式来管理程序的运行日志。
1.2 基本应用案例
# echo "This is a simple sample text 1" > temp.txt
可以通过 cat temp.txt
查看文件内容可以发现,’回声’的输出内容已经保存到 temp.txt
文件中,且终端屏幕上看不到任何输出信息。
1.2.1输出文本追加到另一文件
# echo "This is a simple sample text 2" > temp.txt
此时此输出已经被追加进文件temp.txt
文件中
说明: >
和 >>
为用于重定向文件的操作符,>
先清空文件,再写入内容;>>
将内容追加到现有文件的尾部。
cat temp.txt
可查看文件内容为:
# cat temp.txt
echo "This is a simple sample text 1
echo "This is a simple sample text 2
1.3 文件描述符基本使用
在 Linux 操作系统中,重定向操作符默认使用stdout
, 所以当使用重定向操作符时,重定向的内容不会出现在终端,而是直接被导入文件。如果我想进行更复杂的处理,比如想把某个脚本的输出都存储到对应的文件;或者要求更高一点,指定此脚本标准输出到一个文件,而标准错误到另一个日志文件该怎么处理?
这个时候,因为有涉及到指定的标准输入输出,此时则需要在使用重定向的时候结合文件描述符来达到更严格的目的。文件描述符需要置于操作符之前, 如 1>
。经过分析易得, >
等价于 1>
; >>
等价于1 >>
。
1.3.1标准错误打印到屏幕上
# ls +
ls: cannot access +: No such file or directory
# echo $?
2
+
为非法参数,直接返回错误信息当一个命令发生错误并退出时,它会返回一个非0的退出状态;而当命令成功完成后,它会返回数字0退出状态可以从特殊变量 $?
中获得(在命令执行语句之后执行 echo$?
可以打印出退出状态)
1.3.2 标准错误打印到文件中
# ls a > out.txt
ls: cannot access a: No such file or directory
# ls a 2> out.txt
# cat out.txt
ls: cannot access a: No such file or directory
当执行 ls +
时由于错误而退出,后面的重定向操作符失效。加上文件描述符 2>
则指定将错误输出到指定文件。
1.4 文件描述符与操作符的综合应用
1.4.1 重定向到相同文件
将 stderr 和 stdout 都被重定向到同一个文件 output.txt
。这里的 cmd
表示相关执行命令。
# cmd 2>&1 output.txt
&
并没有固定意思,而是表示重定向的目标不是一个文件,而是一个文件描述符。比如,如果是 1>2
的话,看起来就像是将文件 1
重定向到稳健 2
一样,所以加以 &
来表示操作对象。
1.4.2 重定向到不同文件
将 stderr 单独重定向到一个文件 stderr.txt
,将 stdout 重定向到另一个文件stdout.txt
# cmd 2>stderr.txt 1>stdout.txt
1.5 tee 的使用
1.5.1 在终端打印 stdout ,同时重定向到另一个文件
要在终端中打印 stdout,同时将它重定向到一个文件中,那么可以这样使用tee:
# cmd| tee file1 file2
再如以下案例:
# cat out.txt |tee output.txt|cat -n
1 This is a simple sample text1
2 This is a simple sample text2
# cat output.txt
This is a simple sample text1
This is a simple sample text2
tee 命令接收到来自 stdin 的数据。它将 stdout 的一份副本写入文件 out.txt
, 同时将别一份副本作为后续命令的 stdin。命令cat -n
将从stdin中接收到的每一行数据前加上行号并写入stdout 。
默认情况下,tee 命令会将文件覆盖,但是提供了一个 -a
选项,可以用于追加内容。
1.6 /dev/null 文件的使用
# cmd 2>/dev/null
这个实例会将来自 stderr 的输出丢到文件 /dev/null
中。/dev/null
为一个特殊的设备文件。而这个这个文件接收到的数据都会被丢弃。null 设备也被称为 位桶
或黑洞。