Linux - 输出重定向及log4cpp第三方库的使用

一、标准输入(stdin)、标准输出(stdout)和标准出错(stderr)

通常情况下,Linux/Unix每个程序在运行时会打开3个流分别用于标准输入(stdin,文件描述符为0)、标准输出(stdout,文件描述符为1)和标准出错(stderr,文件描述符为2)。通常他们会被连接到用户终端。这3个句柄的类型为指向FILE的指针。可被fprintf、fread等函数所使用。
Linux的本质就是一切皆文件,输入输出设备也是以文件的形式存在和管理的。
注意: stderr不进行缓存,stdout则进行行间缓存,具体可参考以下代码:

// 示例代码:不带换行符
#include <stdio.h>
#include <unistd.h>

int main() {

    for(int i = 0; i < 5; ++i){
        fprintf(stdout, "stdout No.%d", i);
        sleep(1);    // 休眠一秒
    }

    fprintf(stdout, "\n");	// 此处一起输出fprintf(stdout,"stdout No.%d);的结果

    for(int i = 0; i < 5; ++i) {
        fprintf(stderr, "stderr No.%d", i);	// 此处每个一秒输出一次fprintf(stderr, "stderr No.%d", i);的结果
        sleep(1);
    }

    return 0;
}
// 示例代码:带换行符
#include <stdio.h>
#include <unistd.h>

int main() {

    for(int i = 0; i < 5; ++i){
        fprintf(stdout, "stdout No.%d\n", i);	// 此处每个一秒输出一次
        sleep(1);    // 休眠一秒
    }

    fprintf(stdout, "\n");

    for(int i = 0; i < 5; ++i) {
        fprintf(stderr, "stderr No.%d\n", i);	// 此处每个一秒输出一次
        sleep(1);
    }

    return 0;
}

二、输出重定向

  1. 运行程序时重定向
符号含义
> outfile标准输出重定向到文件(outfile)
< infile标准输入重定向到文件(infile)
< infile > outfile将标准输入重定向到文件(infile)、标注输出重定向到文件(outfile)
> outfile 2>&1标准输出和标准出错重定向到文件
>> outfile以追加的方式输出到文件

示例如下:

#include <stdio.h>

int main(int argc, char** argv)
{
    printf("welcome to qiniu!\n");
    fprintf(stdout, "I am martin!\n");
    perror("are you all ready?\n");
    fprintf(stderr, "Martin always stay with you!\n");

    return 0;
}

Shell下输入: ./test > out.txt

  1. 在代码中重定向
#include <stdio.h>

int main(int argc, char **argv) {

    FILE *out = freopen("stdout.txt", "w", stdout);
    printf("hello everyone!\n");

    return 0;
}

总的来说,stdin,stdout,stderr和终端有密切关系。通常在生产环境下,会将这3个流重定向到其他文件。

打印日志时,通常还会加上如下信息:__ FILE __ 、 __ LINE __ 、 __ FUNCTION __ 、 __ DATE __ 、 __ TIME __ [此处为避免富文本,在__ 与 文字之间加了空格,实际使用时需要去掉]

提示:因为printf涉及到文件,这会引起IO中断。因此执行printf比执行一般指令的效率要低很多。

三、log4cpp的使用

我们使用重定向去输出日志到日志文件中,但是这样的方式还有很多不足,比如无法输出到多个文件、无法设置日志文件的大小、不方便设置日志的级别… log4cpp就提供了很多功能,帮助我们应用程序更方便地记录日志。

  1. log4cpp的安装
    log4cpp链接:log4cpp

步骤如下

  1. 将权限切换至root
  2. 输入如下命令下载:wget https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz
  3. 输入如下命令解压文件:tar -xzvf log4cpp-1.1.3.tar.gz
  4. 输入如下命令配置log4cpp-1.1.3: ./configure
    提示:默认安装至 /usr/local,如需安装到其他位置,则在运行configure时指定 --prefix=< location >,此处安装在项目文件加下的third目录中 [/home/myuser/project/third]
  5. 输入如下命令编译文件:make
  6. 输入如下命令安装:make install
  1. 示例程序

文件 Logger.h

#ifndef _SHARE_BIKE_COMMON_LOGGER_H_
#define _SHARE_BIKE_COMMON_LOGGER_H_

#include <string>
#include <log4cpp/Category.hh>

class Logger {
public:
        bool init(const std::string& log_conf_file);

        static Logger* instance() { return &_instance; }

        log4cpp::Category* GetHandle() { return _category; }

protected:
        static Logger _instance;                // 单例模式
        log4cpp::Category* _category;
};

#define LOG_INFO        Logger::instance()->GetHandle()->info
#define LOG_DEBUG       Logger::instance()->GetHandle()->debug
#define LOG_ERROR       Logger::instance()->GetHandle()->error
#define LOG_WARN        Logger::instance()->GetHandle()->warn

#endif // !_SHARE_BIKE_COMMON_LOGGER_H_

文件 Logger.cpp

#include "Logger.h"

#include <iostream>
#include <log4cpp/FileAppender.hh>	// 此处在CMakeLists.txt中指定包含目录
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/RemoteSyslogAppender.hh>
#include <log4cpp/PropertyConfigurator.hh>

Logger Logger::_instance;

bool Logger::init(const std::string& log_conf_file) {
        try {
                log4cpp::PropertyConfigurator::configure(log_conf_file);
        }
        catch (log4cpp::ConfigureFailure& f) {
                std::cerr << "load log config file (" << log_conf_file.c_str() << ") failed with result:"
                        << f.what() << std::endl;
                return false;
        }

        _category = &log4cpp::Category::getRoot();
        return true;
}

文件 main.cpp

#include "Logger.h"

int main(int argc, char** argv) {
    if (argc < 2) {
        printf("Please input share bike <log file config>.\n");
        return -1;
    }

    if (!Logger::instance()->init(std::string(argv[2]))) {
        fprintf(stderr, "init log module failed.\n");
        return -2;
    }

    LOG_INFO("this is a INFO log.\n");
    LOG_DEBUG("This is a DEBUG log.\n");
    LOG_ERROR("This is an ERROR log.\n");
    LOG_WARN("This is a WARN log.\n");

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值