【转载】IO重定向与文件描述符

来源:互联网 发布:培训ppt课件优化怎么做 编辑:程序博客网 时间:2024/06/03 16:42

原始出处:http://adelphos.blog.51cto.com/2363901/1598570
注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。

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 来禁止输出。

  1. 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>>

  1. 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| 即为过滤器

  2. 重定向
    即不使用系统默认的标准输入输出,而是重新指定,即输入重定向,输出重定向,错误输出重定向,
    双重输出重定向(一次单独地送到不同的地方)。IO重定向其实就是让已创建的FD指向其它的文件(修改其链接的文件)。输入输出数据流的位置用FD标识。
    IO重定向的原理就是通过exec 来操作FD(修改FD所指向的文件),来实现将输入和输出设定为指定的文件(或设备)。关于重定向需要注意:
    I/O重定向与 FD有关,shell的FD通常为10个,即 0~9;
    在IO重定向中,stdout 与 stderr 的管道会先准备好,才会从 stdin 读取文档;
    重定向操作发生的时间是在命令执行开始之前
    对同一个文件描述符多次进行重定向操作,后发生的会覆盖先发生的操作,重定向的最终结果是最后一次重定向命令
    tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份到文档中去;
    bash(ksh)执行命令的过程:分析命令-变量求值-命令替代(“和$( ))-重定向-通配符展开-确定路径-执行命令;
    ( ) 将 command group 置于子shell 去执行,它会继承父shell的Standard 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 会导致整个块设备的数据丢失

  1. IO重定向符号汇总

cmd n>file
将FD为n的输出写入file
cmd >file
标准输出写入file中 FD为1,即将标准输出重定向到file

为1>的简写形式
cmd n

!/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>test12>test2[ade@htest] cat test1
this is normal output
redirect this line to standard output
[ade@h test]$ cat test2
this is an error

  1. 脚本中代码块重定向
    代码重定向是指在代码块内将标准输入或标准输出重定向到文件,而代码块之外而保持默认状态(即重定向只对代码块有效,而不是整个脚本),它可以让代码块方便的处理一个文件,它也是脚本中的临时重定向,特别之处是它针对的是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

  1. 脚本中永久重定向所有命令
    当希望将脚本中的很多输出都重定向时,可以使用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.shthisisthestartofthescriptthefollowingcommandwillredirectallouptputtotestout[ade@htest] 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输入输出错误重定向

0 0