Linux Basics-重定向与管道:第一部分
概述
本教程将介绍 Linux 中重定向标准 IO 流的基本技术。学习:
-
什么是重定向与标准 IO 流:标准输入、标准输出和标准错误
-
各种流和管道的实际应用
前提条件
你应该了解 Linux 基本知识以及拥有一个正常工作的 Linux 系统,在本文说明的实例中,我采用是CentOS 7 内核版本是3.10,它适用于大多数linux(如果不知道自己的内核版本,可以通过在命令行中输入命令uname -a来查询 )
重定向和流
在linux发展到今天,许多工作是通过脚本来完成,这样做的好处就是可以提高效率,而且运维人员可以做到自动化的运维,省去了每天重复一样的操作,而且也避免了因为个人失误而带来的许多问题,想要做到自动化运维就少不了要编写bash脚本,linux中重要的哲学就是避免要和用户交互,而且重定向和流的使用就是完全符合了这样的要求。
概念介绍
文件描述符(File descriptor)
在操作系统中每个程序的打开都要经过系统管理,而系统管理进程或者程序的运行就是通过文件描述符来管理,文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。每个Unix进程(除了可能的守护进程)应均有三个标准的POSIX文件描述符,对应于三个标准流:
整数值 |
名称 |
<stdio.h>文件流 |
0 |
stdin |
|
1 |
stdout |
|
2 |
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 . 输出重定向
从上述例子可以看出 文件描述符不同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。如果文件不存在,它将被创建。
如下所示
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 的输入重定向
LIST 4 . 使用 here-document 的输入重定向
<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>&1与ls 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