深入了解Linux I/O重定向

简介:

一个文件描述符说白了就是文件系统为了跟踪这个打开的文件而分配给它的一个数字,也可以的将其理解为文件指针的一个简单版本,与C语言中文件句柄的概念很相似。

深入了解Linux I/O重定向

Linux 中默认情况下始终有 3 个“文件”处于打开状态,stdin(键盘)、 stdout(屏幕)和 stderr(错误消息输出到屏幕上)。这 3 个文件和其他打开的文件都可以被重定向。重定向,简单的说就是捕捉一个文件、命令、程序、脚本,或者是脚本中的代码块的输出,然后将这些输出作为输入发送到另一个文件、命令、程序或脚本中。

每个打开的文件都会被分配一个文件描述符。stdin、stdout 和 stderr 的文件描述符分别是 0、1 和 2。除了这 3 个文件,对于其它那些需要打开的文件,保留了文件描述符 3 到 9。在某些情况下,将这些额外的文件描述符分配给 stdin、stdout 或 stderr 作为临时的副本链接是非常有用的。在经过复杂的重定向和刷新之后需要把它们恢复成正常状态。

重定向

> file

将 stdout 重定向到一个文件。如果这个文件不存在,那就创建,否则就覆盖。

创建一个包含目录树列表的文件:

 
 
  1. ls -lR >dir-tree.list 

清空文件:

 
 
  1. : > file 

这是一个 > 操作,将会把文件 file 变为一个空文件(就是 size 为 0)。如果文件不存在,那么就创建一个 0 长度的文件(与touch 的效果相同)。: 是一个占位符,不产生任何输出。

也可以省略 : 占位符:

 
 
  1. > file 

与上边的 : > 效果相同, 但是某些 shell (比如 bash)可能不支持这种形式。

>> file

将 stdout 重定向到一个文件。如果文件不存在,那么就创建它,如果存在,那么就追加到文件后边。

 
 
  1. script.sh 1 > filename  
  2. # 重定向 stdout 到文件"filename" 
  3. script.sh 1 >> filename  
  4. # 重定向并追加 stdout 到文件"filename" 
  5. script.sh 2 > filename  
  6. # 重定向 stderr 到文件"filename" 
  7. script.sh 2 >> filename  
  8. # 重定向并追加 stderr 到文件"filename"

&> file

将 stdout 和 stderr 都重定向到文件:

 
 
  1. script.sh &> /dev/null 

m> file

m 是一个文件描述符,如果没有明确指定的话默认为 1。

file 是一个文件名。文件描述符 m 被重定向到文件 file。

 
 
  1. script.sh 2> error.log 

m>&n

m 是一个文件描述符,如果没有明确指定的话默认为 1。

n 是另一个文件描述符。

 
 
  1. script.sh 2>&1 

重定向 stderr 到 stdout。将错误消息的输出,发送到与标准输出所指向的地方。

 
 
  1. exec 6<>File
  2. script.sh >&6 

默认的,重定向文件描述符 1(stdout)到 6。所有传递到 stdout 的输出都送到 6 中去。

< file

从文件中接受输入。与 > 是成对命令,并且通常都是结合使用。0 < file 或 < file,前面的标准输入 stdin 0 可以省略。

 
 
  1. grep search-word < filename 

j<>file

为了读写 file,把文件 file 打开,并且将文件描述符 j 分配给它。

如果文件 file 不存在,那么就创建它。如果文件描述符 j 没指定,那默认是标准输入 stdin 0 。

 
 
  1. echo 1234567890 > File ### 写字符串到 File .  
  2. exec 3<>File ### 打开 File 并且将 fd 3 分配给它.  
  3. read -n 4 <&3 ### 只读取4个字符.  
  4. echo -n . >&3 ### 写一个小数点.  
  5. exec 3>&- ### 关闭fd 3.  
  6. cat File ### ==> 1234.67890 

(注:上述命令的输出结果和原文不同,原因未知。)

管道

管道与 > 很相似,但是实际上更通用。对于想将命令、脚本、文件和程序串连起来的时候很有用。

 
 
  1. cat *.txt | sort | uniq > result-file 

上述命令对所有 .txt 文件的输出进行排序,并且删除重复行。最后将结果保存到 result-file 中。

可以将输入输出重定向和/或管道的多个实例结合到一起写在同一行上:

 
 
  1. command < input-file > output-file 

等价于:

 
 
  1. < input-file command > output-file 

但是这种写法不标准,有的 shell 可能不支持。

可以将多个输出流重定向到一个文件上:

 
 
  1. ls -yz >> command.log 2>&1 

将错误选项 yz 的结果放到文件 command.log 中。因为 stderr 被重定向到这个文件中,所以所有的错误消息也就都指向那里了。

注意,下边这个例子就不会给出相同的结果:

 
 
  1. ls -yz 2>&1 >> command.log 

输出一个错误消息,但是并不写到文件中。命令的输出(如果有的话)写入到文件 command.log。

如果同时将 stdout 和 stderr 都重定向,命令的顺序不同会带来不同的结果。

关闭文件描述符

  • n<&- 关闭输入文件描述符 n。
  • 0<&- 或 <&- 关闭 stdin。
  • n>&- 关闭输出文件描述符 n。
  • 1>&- 或 >&- 关闭 stdout。

子进程继承了打开的文件描述符。这就是为什么管道可以工作的原因。如果想阻止文件描述符被继承,那么可以关掉它。

只将 stderr 重定到一个管道。

 
 
  1. exec 3>&1 ### 保存当前 stdout 的"值"(将 fd3 指向 fd0 相同目标)  
  2. ls -l 2>&1 >&3 3>&- | grep bad 3>&-### 对'grep'关闭 fd 3  
  3. ### ^^^^ ^^^^ ###(但不关闭'ls',正常输出内容不受grep影响)  
  4. ls -l 2>&1 >&3 | grep bad ### 这样输出内容被转到了 fd3,也不会受 grep 影响  
  5. ls badabc -l 2>&1 >&3 |grep bad ### stderr 通过 fd1 输出,会受 grep 影响  
  6. exec 3>&- ### 对于剩余的脚本来说,关闭它 

使用文件描述符 5 可能会引起问题。当 Bash 使用 exec 创建一个子进程的时候,子进程会继承文件描述符 5 (参考 Chet Ramey 的归档 e-mail: RE: File descriptor 5 is held open)。 最好还是不要去招惹这个特定的文件描述符 5 。





作者:Mendel Cooper
来源:51CTO
目录
相关文章
|
3月前
|
Unix Linux C语言
Linux重定向:深入理解与实践
Linux重定向:深入理解与实践
|
3月前
|
Linux
Linux dup函数文件重定向
dup函数创建一个新的文件描述符,该新文件描述符和原有文件描述符file_descriptor指向相同的文件、管道或者网络连接。并且dup返回的文件描述符总是取系统当前可用的最小整数值。dup2和dup类似,不过它将返回第一个不小于file_descriptor_two的整数值。dup和dup2系统调用失败时返回-1并设置errno。有时我们希望把标准输入重定向到一个文件,或者把标准输出重定向到一个网络连接(比如CGI编程)。
19 0
|
4月前
|
缓存 网络协议 Unix
Linux(UNIX)五种网络I/O模型与IO多路复用
Linux(UNIX)五种网络I/O模型与IO多路复用
107 0
|
4月前
|
Linux Shell PHP
linux(十五)文件和目录相关命令-控制台输出命令echo和重定向
linux(十五)文件和目录相关命令-控制台输出命令echo和重定向
48 0
|
5月前
|
弹性计算 运维 Shell
Linux加强篇003-管道符、重定向与环境变量
山重水复疑无路,柳暗花明又一村
248 1
|
1月前
|
缓存 Ubuntu 网络协议
Linux系统编程之文件I/O函数的使用:介绍文件I/O函数的基本概念、用法和实现方式
Linux系统编程之文件I/O函数的使用:介绍文件I/O函数的基本概念、用法和实现方式
20 1
|
24天前
|
监控 网络协议 Linux
Linux I/O多路复用深入解析:从select到epoll的演进之路
Linux I/O多路复用深入解析:从select到epoll的演进之路
62 0
|
存储 Shell Linux
Linux--文件(2)-重定向和文件缓冲
Linux--文件(2)-重定向和文件缓冲
|
5月前
|
存储 缓存 数据管理
深入理解Linux内核I/O机制:探索文件系统与设备驱动(上)
深入理解Linux内核I/O机制:探索文件系统与设备驱动
|
2月前
|
Linux C++
认识Linux指令之 “ 重定向” 符号
认识Linux指令之 “ 重定向” 符号
认识Linux指令之 “ 重定向” 符号