1.介绍

IO重定向用于捕捉一个文件,命令,程序,脚本或者代码块的输出,然后把捕捉到的输出作为输入发送给另外一个文件,命令,程序或脚本。

终端程序一般从单一源以流的形式聚集输入和显示输出,script执行时(进程), 系统会默认开启3个标准文件,stdin, stdout,stderr . script默认会由stdin读取数据,默认键盘,由stdout输出执行结果,默认屏幕; 若有错误发生,则由stderr显示信息,默认指向屏幕系统开启这3个文件时,以文件代码(分别为0,1,2)作为连接,这三个文件被称为标准I/O.Linux Shell 环境中支持标准输入输出重定向,用符号<和>来表示,故可以用来指定需要重定向的标准输入或输出,比如 2>a.txt 表示将错误信息输出到文件a.txt中。

同时,还可以在这三个标准输入输出之间实现重定向,比如将错误信息重定向到标准输出,可以用 2>&1来实现。常用的用法之一是将输出重定向至 /dev/null 来禁止输出。

 

2. file descriptor FD

进程必须先打开一个文件,才能读取或写入文件,Linux进程通过给每个当前被打开的文件赋整数值(从0开始)来追踪文件,这个整数被称为文件描述符,之后对此文件的操作都使用FD来完成。Linux通过/proc 文件系统来检查当前运行进程打开的文件和文件描述符/proc/pid/fd,pid 即对应进程ID,fd 文件夹下以整数文件描述符命名的符号链接,链接到打开文件本身。

每一个I/O管道被用一个整数命名,文件描述符可以与常规文件、设备节点、网络套接字连接(即在虚拟文件系统/proc中,以数字命令的链接文件,链接到指定文件)

  其中0,1,2三个特殊的FD,就是STDIN,STDOUT,STDERR,分别指向相应的设备文件

标准输入STDIN:程序读取的源

标准输出STDOUT:程序写入的目的地

标准错误STDERR:程序将出错状况报告给一个叫标准错误stderr 的目的地

 

FD

默认输出位置

重定向操作符

STDIN

0

keyboard input

(0)<    (0)<<  

STDOUT

1

mointor

(1)>    (1)>>

STDERR

2

monitor

2>    2>>

 

3. Pipeline and redirection

  Pipe将多个命令连接在一起,是Linux的一种基本的进程间通信技术。它的设计符合Unix哲学:复杂的系统应该由简单的、专门的、互操作简单的组件构成,故许多标准Linux程序被设计为过滤器。

管道:把一个进程的标准输出流与另一个进程的标准输入流连接起来,管道符|用于连接一个命令的标准输出与另一条命令的标准输入

pipe 命令:pipe 后面接的第一个数据必定是指令,且这个指令必须能够接受stdin 数据并处理, pipe 命令仅处理stdout , 而忽略stderr ,并将处理结果传递给标准输出,如grep , head, tail, cut, sort, expand,sed,awk,fmt,tac,tr,grep,nl,pr , sed ,awk

过滤器(filters):用来接收标准输入,经过过滤器命令的转化,再写到标准输出。如cat test | grep ade| tac |grep| 即为过滤器

 

 

4. 重定向

即不使用系统默认的标准输入输出,而是重新指定,即输入重定向,输出重定向,错误输出重定向,

双重输出重定向(一次单独地送到不同的地方)IO重定向其实就是让已创建的FD指向其它的文件(修改其链接的文件)输入输出数据流的位置用FD标识。

IO重定向的原理就是通过exec 来操作FD(修改FD所指向的文件),来实现将输入和输出设定为指定的文件(或设备)。关于重定向需要注意:

  1.  I/O重定向与 FD有关,shellFD通常为10个,即 09 
  2. IO重定向中,stdout stderr 的管道会先准备好,才会从 stdin 读取文档;
  3. 重定向操作发生的时间是在命令执行开始之前
  4. 对同一个文件描述符多次进行重定向操作,后发生的会覆盖先发生的操作,重定向的最终结果是最后一次重定向命令 
  5.  tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份到文档中去;
  6. bashksh)执行命令的过程:分析命令-变量求值-命令替代(``$( ))-重定向-通配符展开-确定路径-执行命令;
  7. ( ) command group 置于子shell 去执行,它会继承父shellStandard input, output, and error any other open file descriptors, 这就是为什么子shell中执行的命令输出也一样会打印到屏幕。

 

 

基本IO重定向

cmd > file stdout 重定向到 file 文件中;

cmd 1> file 同上

cmd >> file stdout 重定向到 file 文件中(追加)

cmd 2> file stderr 重定向到 file 文件中;

cmd 2>> file stderr 重定向到 file 文件中(追加)

 

cmd > file 2>&1 stderr stdout 一起重定向到 file 文件中;

cmd &>file  上一例的简写形式

cmd >> file 2>&1 stderr stderr 一起重定向到 file 文件中(追加)

cmd >/dev/null 2>/dev/null 不记录标准输出或标准错误输出

cmd &>/dev/null 同上

 

cmd < file cmd 命令以 file 文件作为 stdin

cmd < file >file2 cmd 命令以 file 文件作为 stdin,以 file2 文件作为 stdout

cmd << delimiter Here document,从 stdin 中读入,直至遇到 delimiter 分界符。

 

示例说明

find / -name 2>/dev/null

date>file1  标准输出无内容,file1中有内容。(先执行重定向)

(date)>file1  标准输出无内容,file1中有内容。(先将子shell 标准输出重定向至file1)

(date >file1) >file2 file1中有内容,file2中无内容。(将子shell 标准输出重定向至file2;shell,date标准输出重定向至file1,shell标准输出没有内容,file1中有内容)

date >file1 >file2  file1中无内容,file2中有内容。(date 标准输出重定向至file1,然后再将date标准输出重定向至file2,都是针对同一个文件描述符,会覆盖.

 

> test.txt 新建空白文件,或者清空文件(危险命令), 多用于清空日志

> /dev/sda 会导致整个块设备的数据丢失

 

 

5. IO重定向符号汇总

 

cmd n>file

FDn的输出写入file

cmd >file

标准输出写入file FD1即将标准输出重定向到file

>  1>的简写形式

cmd n<file

file读入到FD n

cmd <file

file 读入标准输入中 FD0, 即将标准输入重定向到file

< 0<的简写形式

cmd n>>file

FDn的输入追加写入到file

cmd >>file

追加输出至file,FD1

cmd >|file

忽略shellnoclobber选项,强制覆盖file

cmd  n>|file

忽略noclobber选项(shell选项),强制将FDn的输出写入file

cmd n>>|file

忽略noclobber选项

<<delimiter

here-document

cmd1 | cmd2

管道符|(特殊IO重定向), cmd1的标准输出作为cmd2的标准输入

 

5.脚本中临时重定向每一行

此方法可以为生成错误消息提供方便

cat retest.sh

#!/bin/bash

echo "this is an error" >&2                 #重定向至指定FD,此处重定向至标准错误输出

echo "this is normal output"

echo "redirect this line to standard output" >&1

 

[ade@h test]$ ./test.sh >test1 2>test2

[ade@h test]$ cat test1

this is normal output

redirect this line to standard output

[ade@h test]$ cat test2

this is an error

 

7. 脚本中代码块重定向

代码重定向是指在代码块内将标准输入或标准输出重定向到文件,而代码块之外而保持默认状态(即重定向只对代码块有效,而不是整个脚本),它可以让代码块方便的处理一个文件,它也是脚本中的临时重定向,特别之处是它针对的是shell脚本中相应的结构代码。

while,until,for,if/then, 函数等代码块都可以使用重定向,<输入重定向,>输出重定向。

 

cat rewhile.sh

#!/bin/bash

 

ls /etc > loggg

while [ "$filename" != "rc.d" ]

do

read filename

let "count +=1"

done < loggg

 

echo "$count times read"

 

#测试循环体外的标准输入是否被重定向

echo -n " ------pls input data:---------"

read test

echo $test

 

 

cat reif.sh

if [ -z "$1" ]

then

echo "positional parameter is null"

fi > loggg

echo "-----------Normal stdout--------"

 

 

其它结构的重定向

for

do

......

done < loggg

 

if [condition]

then

...

else

...

fi < loggg

 

until [condition]

do

    ...

done < loggg

 

 

8. 脚本中永久重定向所有命令

当希望将脚本中的很多输出都重定向时,可以使用exec 通知shell在脚本执行时重定向特定的文件描述符。实例上是使用exec 来完成FD的相关操作。

 cat test1.sh

#!/bin/bash

 

exec 1>testout

echo "line one"

echo "line two"

echo "line three"

 

 

 cat test.sh

#!/bin/bash

 

exec 2>testerr

echo "this is the start of the script"

 

echo "the following command will redirect all ouptput to testout"

exec 1> testout    #or exec > testout

 

echo " put this line into testout"

echo "put this line into testerr" >&2

 

[ade@h test]$ ./test.sh

this is the start of the script

the following command will redirect all ouptput to testout

[ade@h test]$ cat testout

 put this line into testout

[ade@h test]$ cat testerr

put this line into tester

 

 

refer

Linux下输入输出重定向

Linux重定向(百度百科)

man bash   here documents 部分

awk, fold, grep, head, nnkf, pr, sed, sort, tail, tee, tr, uniq, wc

exec

lsof  : 列出所有开放的文件描述符

here-document

Linux输入输出错误重定向