Skip to content

Latest commit

 

History

History
90 lines (67 loc) · 3.05 KB

11.1_重定向.md

File metadata and controls

90 lines (67 loc) · 3.05 KB

11.1 重定向

stdin, stdout, stderr是什么

  在通常情况下,UNIX每个程序在开始运行的时刻,都会有3个已经打开的stream. 分别用来输入,输出,打印诊断和错误信息。通常他们会被连接到用户终端(tty(4)). 但也可以改变到其它文件或设备。这取决于双亲进程的选择和设置。   这3个symbols都是stdio(3) macro,类型为指向FILE的指针。可以被fprintf、fread等函数使用。   既然这几个是文件,那么他们在程序开始启动后,stdin, stdout, and stderr 的文件描述符是 0, 1和2,其它的文件描述符则排在其后。   Linux的本质就是一切皆文件,输入输出设备也是以文件形式存在和管理的。   stderr是不缓存的,stdout是行间缓存的。行间缓存是什么意思呢?我们来看一段代码:
#include "stdio.h"

int main(int argc, char** argv)
{
    for(int i = 0; i < 10; i++)
    {
        fprintf(stdout, "This is stdout[%d]", i);
        fprintf(stderr, "This is stderr[%d]", i);
    }

    return 0;
}

还有一段程序如下:

#include "stdio.h"

int main(int argc, char** argv)
{
    for(int i = 0; i < 10; i++)
    {
        fprintf(stdout, "This is stdout[%d]\n", i);
        fprintf(stderr, "This is stderr[%d]\n", i);
    }

    return 0;
}

细心的朋友们一定会发现,我们就是在打印的时候加上了"\n"而已,哦去敲入代码吧,看看有什么不一样。   我们很多同学喜欢用printf打印信息来调试程序,但是如果终端关掉了,那怎么显示printf的调试信息呢?

重定向

我们来先看这段程序(文件名test.c):
#include <stdio.h>

int main(int argc, char** argv)
{
    printf("welcome to dongnao!\n");
    fprintf(stdout, "i am lee ge!\n");
    perror("are you all ready!\n");
    fprintf(stderr, "Lee ge always stay with you!\n");

    return 0;
}

编译好后(gcc -o test test.c),我们试试下面不同的运行方式: ./test > test.txt
./test 1 > testout.txt ./test 2 > testerr.txt
./test > test.txt 2>&1

当然除了使用“>”重定向外,我们还可以试下“>>”,另外我们还可以在代码中实现重定向,比如:

#include <stdio.h>
 
int main(void)
{
    FILE *out = freopen("stdout.txt", "w", stdout);
    printf("%s\n", "hello verybody!!!");
 
    return 0;
}

总的来说,stdin,stdout和stderr还是和终端有密切关系,通常在生产环境时,会将这3个流重定向到其它文件。比如编写守护进程的时候,因为守护进程和终端无关,所以往往会将stdin,stdout和stderr重定向到/dev/null去。

如果我们实在要用printf或者fprintf去生成日志的话,最好还是加上这些信息,__FILE__ __LINE__ __FUNCTION__, __DATE__, __TIME__。

当然我们一定要明白,printf设计到文件,这会引起IO中断,因此执行printf比一般的指令的效率要低很多。