玩转Linux文件描述符和重定向

发布时间:2019-11-30编辑:脚本学堂
本文介绍linux中文件描述符与重定向的相关知识,文件描述符是与文件输入、输出相关联的整数,它们用来跟踪已打开的文件。有需要的朋友参考下。
本节是 玩转Linux文件描述符和重定向 第二页的内容,欢迎大家继续阅读。

在这个示例中,来自stderr的输出被丢到文件/dev/null中。/dev/null是一个特殊的设备文件,这个文件接收到的任何数据都会被丢弃。

因此,null设备通常也被为位桶(bit bucket)或黑洞。
当对stderr或stdout进行重定向时,重定向的文本将传入文件。

因为文本已经被重定向到文件中,也就没剩下什么东西可以通过管道(|)传给接下来的命令,而这些命令是通过stdin来接收文本的。
但是有一个巧妙的方法可以一方面将数据重定向到文件,另一方面还可以提供一些重定向数据的副本作为后续命令的stdin。

这一切都可以使用tee来实现。

举个例子:要在终端中打印stdout,同时将它重定向到一个文件中,那么可以这样使用tee:
 

复制代码 代码示例:
command | tee FILE1 FILE2
 

在下面的代码中,tee命令接收到来自stdin的数据。它将stdout的一份副写入文件out.txt,同时将别一份副本作为后续命令的stdin。命令cat -n将从stdin中接收到的每一行数据前加上行号并写入stdout:
 

复制代码 代码示例:
$ cat a*| tee out.txt| cat -n
cat: a1: permission denied
 1 a1
2 a1
 

查看out.txt 的内容:
 

复制代码 代码示例:
$ cat out.txt
a1
a1
 

注意,cat:a1:permission denied并没有在任何文件内容中出现。这是因为这些信息属于stderr,而tee只能从stdin中进行读取。
默认情况下,tee命令会将文件覆盖,但是提供了一个-a选项,可以用于追加内容。例如:
 

复制代码 代码示例:
$ cat a*| tee -a out.txt| cat -n.
 

带有参数的命令可以写成:command FILE1 FILE2依次类推,或者简简单单地用command FILE。
我们可以使用stdin作为命令参数。只需要将-作为命令的文件名参数即可:
 

复制代码 代码示例:
$ cmd1 |cmd2 |cmd -
 

例如:
 

复制代码 代码示例:
$ echo who is this | tee-
who is this
who is this
 

或者我们也可以将/dev/stdin作为输出文件名来使用stdin。
类似的,使用/dev/stderr代表标准错误,/dev/stdout代表标准输出。这些特殊的设备文件分别对应stdin、stderr和stdout。

补充内容:
从stdin读取输入的命令能以多种方式接收数据。另外,还可以用cat和管道来制定我们自己的文件描述符,例如:
 

复制代码 代码示例:
$ cat file | cmd
$ cmd1 | cmd2
 

1.将文件重定向到命令
借助重定向,我们可以像使用stdin那样从文件中读取数据:
 

复制代码 代码示例:
$ cmd <file
 

2.重定向脚本内部的文本块
有时候,需要对文本块(多行文本)像标准输入一样进行重定向。考虑一个特殊情况:源文本就位于shell/ target=_blank class=infotextkey>shell脚本中。

来看下面这段shell脚本吧,向log文件中写入头部数据,可以按照下面的方法完成:
 

复制代码 代码示例:
#!/bin/bash
cat <<EOF>log.txt
LOG FILE HEADER
This is a test log file
Function:System statistics
EOF
 

在cat <<EOF>log.txt与下一个EOF行之间的所有文本行都会被当做stdin数据。log.txt文件的内容打印如下:
 

复制代码 代码示例:
$ cat log.txt
LOG FILE HEADER
This is a test log file
Function:System statistics