Linux 重定向

                                        

1、 基本概念(这是理解后面的知识的前提,请务必理解) 

a、 I/O重定向通常与 FD有关,shellFD通常为10个,即 09; 

b、 常用FD3个,为0stdinSTDIN_FILENO 标准输入)、1stdoutSTDOUT_FILENO标准输出)、2stderrSTDERR_FILENO标准错误输出),默认与keyboardmonitormonitor关联; 

c、 用 来改变读进的数据信道(stdin),使之从指定的档案读进; 

d、 用 来改变送出的数据信道(stdout, stderr),使之输出到指定的档案; 

e、 是 的默认值,因此 与 0<是一样的;同理,与 1> 是一样的; 

f、 在IO重定向 中,stdout 与 stderr 的管道会先准备好,才会从 stdin 读进资料; 

g、 管道|(pipe line):上一个命令的 stdout(不包括stderr 接到下一个命令的 stdin; 

h、 tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份到档案去

i、 bashksh)执行命令的过程:分析命令-变量求值-命令替代(``$( ))-重定向-通配符展开-确定路径-执行命令; 

j、 ( ) 将 command group 置于 sub-shell 去执行,也称 nested sub-shell,它有一点非常重要的特性是:继承父shellStandard input, output, and error plus any other open file descriptors。 

k、 exec 命令:常用来替代当前 shell 并重新启动一个 shell,换句话说,并没有启动子 shell。使用这一命令时任何现有环境都将会被清除。exec 在对文件描述符进行操作的时候,也只有在这时,exec 不会覆盖你当前的 shell 环境。 

2、 基本IO

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

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

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

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

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

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

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

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

cat <>file 以读写的方式打开 file; 

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

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

3、 进阶IO 

>&n 使用系统调用 dup (2) 复制文件描述符 并把结果用作标准输出; 

<&n 标准输入复制自文件描述符 n; 

<&- 关闭标准输入(键盘); 

>&- 关闭标准输出; 

n<&- 表示将 号输入关闭; 

n>&- 表示将 号输出关闭; 

上述所有形式都可以前导一个数字,此时建立的文件描述符由这个数字指定而不是缺省的 或 1。如: 

... 2>file 运行一个命令并把错误输出(文件描述符 2)定向到 file。 

... 2>&1 运行一个命令并把它的标准输出和输出合并。(严格的说是通过复制文件描述符 来建立文件描述符 ,但效果通常是合并了两个流。

我们对 2>&1详细说明一下 :2>&1 也就是 FD2FD1 ,这里并不是说FD2 的值 等于FD1的值,因为 是改变送出的数据信道,也就是说把 FD2 的 数据输出通道” 改为 FD1 的 数据输出通道。如果仅仅这样,这个改变好像没有什么作用,因为 FD2 的默认输出和 FD1的默认输出本来都是 monitor,一样的! 但是,当 FD1 是其他文件,甚至是其他 FD 时,这个就具有特殊的用途了。请大家务必理解这一点。 

exec 1>outfilename # 打开文件outfilename作为stdout。 

exec 2>errfilename # 打开文件 errfilename作为 stderr。 

exec 0<&- # 关闭 FD0。 

exec 1>&- # 关闭 FD1。 

exec 5>&- # 关闭 FD5。 

举例如下:

nohup /mnt/Nand3/H2000G  >/dev/null  2>&1  &

 

实际上这个操作就是一个dup2(2)调用. 他把标准输出重定向到/dev/null然后复制文件描述符1STDOUT_FILENO到文件描述符2(STDERR_FILENO), 其后果就是文件描述符12指向同一个文件表项,也可以说错误的输出被合并了.最终结果导致所有输出都到/dev/null 下面去
    command >out.file  2>&1 &
    command >out.file是将command的输出重定向到out.file文件,即输出内容不打印到屏幕上,而是输出到out.file文件中。2>&1 是将标准错误重定向到标准输出,这里的标准输出已经重定向到了out.file文件,即将标准出错也输出到out.file文件中。最后一个, 是让该命令在后台执行。
       
    试想2>1代表什么,2>结合代表错误重定向, 1则代表错误重定向到一个文件1,而不代表标准输出;
换成2>&1&1结合就代表标准输出了,就变成错误重定向到标准输出.

你可以用
        ls 2>1测试一下,不会报没有2文件的错误,但会输出一个空的文件1
        ls xxx 2>1测试,没有xxx这个文件的错误输出到了1中;
        ls xxx 2>&1测试,不会生成1这个文件了,不过错误跑到标准输出了;
        ls xxx >out.txt 2>&1, 实际上可换成 ls xxx 1>out.txt 2>&1;重定向符号>默认是1,错误和输出都传到out.txt了。

为何2>&1要写在后面?
      command > file 2>&1 
      首先是command > file将标准输出重定向到file中, 2>&1 是标准错误拷贝了标准输出的行为,也就是同样被重定向到file中,最终结果就是标准输出和错误都被重定向到file中。 
      command 2>&1 >file 
      2>&1 标准错误拷贝了标准输出的行为,但此时标准输出还是在终端。>file 后输出才被重定向到file,但标准错误仍然保持在终端。

strace可以看到:
1. command > file 2>&1
这个命令中实现重定向的关键系统调用序列是:

 

open(file) == 3
dup2(3,1)
dup2(1,2)

 

2. command 2>&1 >file
这个命令中实现重定向的关键系统调用序列是:

 

dup2(1,2)
open(file) == 3
dup2(3,1) 

可以考虑一下不同的dup2()调用序列会产生怎样的文件共享结构。请参考APUE 3.10, 3.12

关于dup2系统调用

Name

dup, dup2, dup3 - duplicate a file descriptor 

Synopsis

#include <unistd.h>

int dup2(int oldfd, int newfd);

Description

These system calls create a copy of the file descriptor oldfd. 

dup() uses the lowest-numbered unused descriptor for the new descriptor.

dup2() makes newfd be the copy of oldfd, closing newfd first if necessary, but note the following:

*  If oldfd is not a valid file descriptor, then the call fails, and newfd is not closed.

*  If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing, and returns newfd.

After a successful return from one of these system calls, the old and new file descriptors may be used interchangeably. They refer to the same open file description (see open(2)) and thus share file offset and file status flags; for example, if the file offset is modified by using lseek(2) on one of the descriptors, the offset is also changed for the other.

The two descriptors do not share file descriptor flags (the close-on-exec flag). The close-on-exec flag (FD_CLOEXEC; see fcntl(2)) for the duplicate descriptor is off.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值