目录
一、stdin/stdout/stderr
在通常情况下,Linux/UNIX每个程序在开始运行的时刻,都会打开3个已经打开的stream. 分别用来输入,输出,打印诊断和错误信息。通常他们会被连接到用户终端。这3个句柄的类型为指向FILE的指针。可以被fprintf、fread等函数使用,他们在程序开始启动后,stdin, stdout, and stderr 的文件描述符是 0, 1和2,其它的文件描述符则排在其后。
Linux的本质就是一切皆文件,输入输出设备也是以文件形式存在和管理的。
注意:stderr是不缓存的,stdout则进行行间缓存。接下来我们看下行间缓存的效果,请参考以下代码:
#include "stdio.h"
#include <unistd.h>
int main(int argc, char** argv)
{
for(int i = 0; i < 5; i++)
{
fprintf(stdout, "This is stdout[%d]", i);
sleep(1);
}
sleep(1);
for(int i = 0; i < 5; i++)
{
fprintf(stderr, "This is stderr[%d]", i);
sleep(1);
}
return 0;
}
比较如下代码:
#include "stdio.h"
#include <unistd.h>
int main(int argc, char** argv)
{
for(int i = 0; i < 5; i++)
{
fprintf(stdout, "This is stdout[%d]\n", i);
sleep(1);
}
sleep(1);
for(int i = 0; i < 5; i++)
{
fprintf(stderr, "This is stderr[%d]\n", i);
sleep(1);
}
return 0;
}
上面两端代码就是在打印的时候加上了"\n"而已,但是效果完全不一样。
思考:很多时候我们会用printf打印信息来调试程序,但是如果终端关掉了,那怎么显示printf的调试信息呢?
1、重定向
我们来先看这段程序(文件名test.c):
#include <stdio.h>
int main(int argc, char** argv)
{
printf("welcome to China!\n");
fprintf(stdout, "I am Hello!\n");
perror("are you all ready?\n");
fprintf(stderr, "Hello 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个流重定向到其它文件。
如果我们实在要用printf或者fprintf去生成日志的话,最好还是加上这些信息,__FILE__ __LINE__ __FUNCTION__, __DATE__, __TIME__。
当然我们一定要明白,printf设计到文件,这会引起IO中断,因此执行printf比一般的指令的效率要低很多。
二、Log4cpp第三方库
参考我另两篇博客: