Linux Basics-重定向与管道:第一部分

Linux Basics-重定向与管道:第一部分

概述

本教程将介绍 Linux 中重定向标准 IO 流的基本技术。学习:

  • 什么是重定向与标准 IO 流:标准输入、标准输出和标准错误

  • 各种流和管道的实际应用

 


前提条件

你应该了解 Linux 基本知识以及拥有一个正常工作的 Linux 系统,在本文说明的实例中,我采用是CentOS 7 内核版本是3.10,它适用于大多数linux(如果不知道自己的内核版本,可以通过在命令行中输入命令uname -a来查询 )

 

重定向和流

在linux发展到今天,许多工作是通过脚本来完成,这样做的好处就是可以提高效率,而且运维人员可以做到自动化的运维,省去了每天重复一样的操作,而且也避免了因为个人失误而带来的许多问题,想要做到自动化运维就少不了要编写bash脚本,linux中重要的哲学就是避免要和用户交互,而且重定向和流的使用就是完全符合了这样的要求。


概念介绍

 文件描述符(File descriptor)

在操作系统中每个程序的打开都要经过系统管理,而系统管理进程或者程序的运行就是通过文件描述符来管理,文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。每个Unix进程(除了可能的守护进程)应均有三个标准的POSIX文件描述符,对应于三个标准流:

整数值

名称

<stdio.h>文件流

0

Standard input

stdin

1

Standard output

stdout

2

Standard error

stderr

 

stdout是 标准输出流,它显示来自命令的输出。它拥有文件描述符 1。

stderr是 标准错误流,它显示来自命令的错误输出。它拥有文件描述符 2。

stdin是 标准输入流,它向命令提供输入。它拥有文件描述符 0。

 

重定向标准 IO

尽管标准输入和输出模型是发往和来自 ASCII 终端的顺序字符流,但是我们想要把文本文件中的字符发给终端,或者是想要上一条命令的结果发给某个文件或者程序,总之需求多多,这个时候就要用到重定向

重定向是以出现的顺序进行处理的,从左到右。

注意重定向的顺序非常重要。例如,命令

ls > dirlist 2>&1

将标准输出和标准错误重定向到文件 dirlist, 而命令

ls 2>&1 > dirlist

只会将标准输出重定向到文件 dirlist, 因为在标准输出被重定向到文件 dirlist 中之前,标 准错误被复制为标准输出。

一些文件名在重定向中被 bash 特殊处理,如下表所示:

/dev/fd/fd

如果 fd 是一个合法的整数,文件描述符 fd 将被复制 。

/dev/stdin

文件描述符 0 被复制。

/dev/stdout

文件描述符1 被复制 。

/dev/stderr

文件描述符2 被复制 。

/dev/tcp/host/port

如果host 是一个合法的主机名或internet地址 ,并且 port 是一个整数端口号或服务名,bash 试图建立与相应的socket (套 接 字 )的TCP连接。

/dev/udp/host/port

如果 host 是一个合法的主机名或Internet地址,并且 port 是一个整数端口号或服务名,bash试图建立与相应的socket (套 接 字 )的UDP连接。

打开或创建文件错误将导致重定向出错 


 1.重定向输出Redirecting Output

它的格式是


[n]>word

 

可通过两种方式将输出重定向到文件:

<1>Redirecting Output 重定向输出

格式:

n>word

将来自文件描述符 n的输出重定向到某个文件。您必须拥有该文件的写权限。如果该文件不存在,则需要创建它。如果它已经存在,通常会毫无预兆地丢失现有内容。

 

<2>Appending Redirected Output (添加到重定向后的输出尾部)

格式:

n>> word

这种方式的输出重定向使得以 word 扩展结名的文件被打开并通过文件描述符 n 从尾部添加。如果文件不存在,它将被创建。如果它已经存在,输出会被附加到现有文件。n> 或 n>> 中的 n指的是 文件描述符。如果省略它,则会假设使用的是标准输出(文件描述符 1)

 

可以使用内建命令 set的 noclobber选项来控制此行为。如果已设置它,可以使用 n>| 覆盖它。如果启用了内建命令 set 的 noclobber 选 项 , 那么如果 word 扩展后得到的文件名 存在并且是一个普通的文件,重定向将失败。 如果重定向操作符是 >|, 或者重定向操作符 是 > 并且没有启用内建命令 set 的 noclobber 选 项 , 那么即使 word 得出的文件名存 在 也会尝试进行重定向。

set -o noclobber命令或者set +C 来控制,set -C来取消,具体操作可以查看man帮助

 

下面是说明的演示:

LIST 1 . 创建准备文件

 

  mkdir -p cdx1&& cd cdx1 && { 
  echo -e "1 magedu\n2 linux\n3 M21" > text1 
  echo -e "4\tlear\n3\tkernel\n10\knowledge" > text2 
  echo "www.magedu.com. " >text3 
  ls; }

 

LIST 2 . 输出重定向

 blob.png

从上述例子可以看出 文件描述符不同n>或者n>>重定向的内容也是不同的,而且n>和n>>作用也是不同,n>>可以重定向到尾部。


拓展知识(自行探索)

有时,您可能希望将标准输出和标准错误都重定向到一个文件中。通常,会对自动化流程或后台作业这么做,以便可以在以后检查输出。使用 &> 或 &>> 将标准输出和标准错误都重定向到同一个位置。另一种方法是重定向文件描述符 n,然后使用结构 m>&n 或 m>>&n 将文件描述符 m重定向到相同位置。重定向输出的顺序很重要。例如,

command 2>&1 >output.txt
不同于 
command >output.txt 2>&1
在第一种情况下,stderr 被重定向到当前的 stdout 位置,然后将 stdout 重定向到 output.txt,但第二次重定向仅会影响 stdout,而不会影响 stderr。在第二种情况下,stderr 被重定向到当前的 stdout 位置,也就是 output.txt

 

Redirecting Standard Output and Standard Error 

Bash 允许使用这种结构将标准输出和标准错误 (文件描述符 1 和 2) 重定向到以 word 扩 展结果为名的文件中。

有两种重定向标准输出/标准错误的形式:

&>word

还 有

>&word

两种形式中 ,推荐使用第一种。它与

>word 2>&1

在语义上等价 。

 

Opening File Descriptors for Reading and Writing 

重定向操作符

[n]<>word

使得以 word 扩展结果为名的文件被打开 ,通过文件描述符n 进行读写。如果没有指定 n 那么就使用文件描述符0。如果文件不存在,它将被创建。

如下所示

 blob.png

blob.png

blob.png

Moving File Descriptors 
重 定 向 操 作 符

[n]<&digit

将文件描述符 digit 移动为文件描述符 n, 或标准输入 (文件描述符 0),如果没有指定 n 的 话 。 digit 复制为 n 之后就被关闭了。

类似的 重定向操作符

[n]>&digit

将文件描述符 digit 移动为文件描述符 n, 或标准输出(文件描述符1),如果没有指定 n 的 话 。

 


<3>Here Documents 
它将 << 和一个单词结合构成一个标记,比如与 END 结合来表示输入结束。LIST 3和4演示了此概念,LIST 3和4使用命令替换创建了一个强制制表符,然后创建了一段仅包含两个 cat命令的很短的 shell 脚本,每个命令从一个 here-document 读取信息。使用 END 作为从终端读取的 here-document 的标记。如果在脚本中使用同一个单词作为标记,则会导致过早结束输入。所以,可使用 EOF 代替。创建脚本后,使用 .(点号)命令 导入它(.(点号)和source命令一样,用于不重启shell来读取脚本或者配置文件生效)。

这种重定向使得shell从当前源文件读取输入 ,直到遇到仅包含 word 的一行(并且没有尾部空白,trailing blanks)为止。直到这一点的所有行被用作命令的标准输入 。

here-document 的格式是:

<<[]word 
here-document 
delimiter

如果重定向操作符是 <<, 那么所有前导的tab 字符都被从输入行和包含 delimiter 的行 中删除。这样使得 shell 脚本中的here-document 可以被更好地缩进。

注意:

  • 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。

  • 开始的delimiter前后的空格会被忽略掉。

  • 格式中word就是delimiter的意思

 


<4>Here Strings 
here-document 的变种 ,形式是

<<<word

word 被扩展 ,提供给命令作为标准输入。

 

LIST 3 . 使用 here-document 的输入重定向

blob.png

 

LIST 4 . 使用 here-document 的输入重定向

 

blob.png

blob.png

 


<5>/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

$ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出“的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

 

$ command > /dev/null 2>&1

 


2. 重定向输入(Redirecting Input )

重定向输入使得以 word 扩展结果为名的文件被打开并通过文件描述符 n 读取 ,如果没有指定 n 那么就作为标准输入(文件描述符为0)读取 。

重定向输入的一般形式是:

[n]<word

 

具体用法参见重定向输出

命令

说明

command > file

将输出重定向到 file。

command < file

将输入重定向到 file。

command >> file

将输出以追加的方式重定向到 file。

n > file

将文件描述符为 n 的文件重定向到   file。

n >> file

将文件描述符为 n 的文件以追加的方式重定向到 file。

n >& m

将输出文件 m 和 n 合并。

n <& m

将输入文件 m 和 n 合并。

<< tag

将开始标记 tag 和结束标记   tag 之间的内容作为输入。


重定向用法整理(来自网络)

简单重定向

  • cmd > file

把cmd命令的输出重定向到文件file中。如果file已经存在,则清空原有文件,使用bash的noclobber选项可以防止覆盖原有文件。

  • cmd >> file

把cmd命令的输出重定向到文件file中,如果file已经存在,则把信息加在原有文件后面。

  • cmd < file

使cmd命令从file读入

  • cmd << text

从命令行读取输入,直到一个与text相同的行结束。除非使用引号把输入括起来,此模式将对输入内容进行shell变量替换。如果使用 <<- ,则会忽略接下来输入行首的tab,结束行也可以是一堆tab再加上一个与text相同的内容,可以参考后面的例子。

  • cmd <<< word

把word(而不是文件word)和后面的换行作为输入提供给cmd。

  • cmd <> file

以读写模式把文件file重定向到输入,文件file不会被破坏。仅当应用程序利用了这一特性时,它才是有意义的。

  • cmd >| file

功能同>,但即便在设置了noclobber时也会覆盖file文件,注意用的是|而非一些书中说的!,目前仅在csh中仍沿用>!实现这一功能。

使用文件描述符的重定向

使用文件描述符的重定向都使用了&符号。

cmd >&n

把输出送到文件描述符n

cmd m>&n

把输出 到文件符m的信息重定向到文件描述符n

cmd >&-

关闭标准输出

cmd <&n

输入来自文件描述符n

cmd m<&n

m来自文件描述符n

cmd <&-

关闭标准输入

cmd <&n-

移动输入文件描述符n而非复制它。(需要解释)

cmd >&n-

移动输出文件描述符 n而非复制它。(需要解释)

注意: 
>&实际上复制了文件描述符,这使得ls > dirlist 2>&1ls 2>&1 > dirlist的效果不一样。man bash的Redirection节中提及了这段内容。

重定向的组合应用

cmd 2>file

把文件描述符2重定向到file,即把错误输出存到file中。

cmd > file 2>&1

把标准错误重定向到标准输出,再重定向到file,即stderr和stdout都被输出到file中

cmd &> file

功能与上一个相同,更为简便的写法。

cmd >& file

功能仍与上一个相同。

cmd > f1 2>f2

把stdout重定向到f1,而把stderr重定向到f2

 


参考资料

IBM中国linux专区

Wiki

Redirection Definition  http://www.linfo.org/redirection.html

网络博客

原创文章,作者:M21-郝建勋,如若转载,请注明出处:http://www.178linux.com/54471

联系我们

400-080-6560

在线咨询

工作时间:周一至周五,9:30-18:30,节假日同时也值班

QR code