您的位置:首页 > 运维架构 > Shell

C语言及shell描述符重定向

2016-07-17 14:59 375 查看
1. dup 和dup2函数

作用:用来复制文件描述符,经常用来重定向进程的stdin、stdout和stderr。

编程中经常会遇到讲标准输出重定向的情况,这可以使用dup2函数来实现,man手册函数定义如下:

DUP(2) BSD System Calls Manual DUP(2)

NAME
dup, dup2 -- duplicate an existing file descriptor

SYNOPSIS
#include <unistd.h>

int
dup(int fildes);

int
dup2(int fildes, int fildes2);
tips:

使用dup2可以讲fildes2描述符重定向到fildes,当fildes2 打开时,会先关闭fildes2

example:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fd = open("/tmp/log", O_RDWR| O_CREAT, S_IRWXU | S_IRWXG | S_IROTH);
if(fd < 0)
{
printf("open log filefailed\n");
return 0;
}
printf("open log file successed, fd =%d\n", fd);

int org_stdout = dup(STDOUT_FILENO);//save stdout

dup2(fd, STDOUT_FILENO); //use ~/log as stdout
printf("hello\n");
close(fd);

dup2(org_stdout, STDOUT_FILENO); //restore stdout
printf("hello\n");

return 0;
}
编译运行后,可以看到hello字符串一个输出到屏幕上,一个输出到/tmp/log文件

 

2. shell重定向

shell中可以使用<,>,<<,>>来重定向标准输入输出,也可以使用exec来操作:

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

常用重定向

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

&-关闭标准输出

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

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

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

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

我们对 2>&1详细说明一下 :

2>&1也就是 FD2=FD1,这里并不是说FD2 的值等于FD1的值,因为 > 是改变送出的数据信道,也就是说把 FD2 的 “数据输出通道”改为 FD1 的 “数据输出通道”。

如果仅仅这样,这个改变好像没有什么作用,因为 FD2 的默认输出和 FD1 的默认输出本来都是 monitor,一样的!但是,当 FD1 是其他文件,甚至是其他 FD 时,这个就具有特殊的用途了。请大家务必理解这一点。

恢复

如果 stdin, stdout, stderr 进行了重定向或关闭, 但没有保存原来的 FD, 可以将其恢复到 default 状态吗?

如果关闭了stdin,因为会导致退出,那肯定不能恢复。

如果重定向或关闭 stdout和stderr其中之一,可以恢复,因为他们默认均是送往monitor(但不知会否有其他影响)。

如恢复重定向或关闭的 stdout: exec1>&2 ,恢复重定向或关闭的stderr:exec 2>&1。

如果stdout和stderr全部都关闭了,又没有保存原来的FD,可以用:exec1>/dev/tty 恢复。

cmd>a 2>a 和 cmd >a 2>&1 为什么不同?

cmd>a 2>a :stdout和stderr都直接送往文件 a ,a文件会被打开两遍,由此导致stdout和stderr互相覆盖。

cmd>a 2>&1 :stdout直接送往文件a ,stderr是继承了FD1的管道之后,再被送往文件a 。a文件只被打开一遍,就是FD1将其打开。

Example:

exec1>outfilename # 打开文件outfilename作为stdout
exec2>errfilename # 打开文件errfilename作为 stderr
exec1&- #关闭FD1
exec5>&- #关闭 FD5

exec4<&1 #备份当前stdout至FD4
exec1>1.txt # stdout重定向至1.txt
exec1<&4 #恢复stdout
exec4>&- #关闭 FD4
2中参考链接:http://xstarcd.github.io/wiki/shell/exec_redirect.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  IO重定向 dup2