gflags和glog - artinfo1982/demos GitHub Wiki
gflags是google的开源命令行参数解析器,glog是google的开源日志系统。
在实际项目中,二者一般结合使用。
git clone https://github.com/gflags/gflags
# 进入gflags文件夹
cmake .
make -j 8
sudo make install
git clone https://github.com/google/glog
sudo apt install autoconf automake libtool
# 进入glog文件夹
./autogen.sh
./configure
make -j 8
sudo make install
# 安装完,默认头文件会在/usr/local/include下,lib文件在/usr/local/lib下
sudo apt install libgflags-dev libgoogle-glog-dev
#include <iostream>
#include <gflags/gflags.h>
// 定义参数变量的默认值,如果命令行不带任何参数,将使用默认值
DEFINE_string(host, "127.0.0.1", "host");
DEFINE_int32(port, 12306, "port");
int main(int argc, char **argv)
{
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << "host: " << FLAGS_host << ", port: " << FLAGS_port << std::endl;
return 0;
}
编译:
g++ test.cpp -o test -lgflags
运行:
# 不带参数(使用默认值)
./test
# 带参数(使用输入的参数值)
./test -host "1.1.1.1" -port 2222
# 一个横杠和两个横杠的效果一样
./test --host "1.1.1.1" --port 2222
DEFINE_XXX()的第三个参数是注释,内容不限,可以写多个"""""",例如:
DEFINE_string(host, "127.0.0.1", "host""aaa""bbb");
DEFINE_int32(port, 12306, "port""111""222");
可以像使用一般的变量一样,使用gflags定义的变量,例如:
FLAGS_port++;
std::cout << "new port: " << FLAGS_port << std::endl;
DEFINE_bool
DEFINE_int32
DEFINE_int64
DEFINE_uint64
DEFINE_double
DEFINE_string
建议在.cc或者.cpp文件中定义gflags变量,DEFINE_string(a, "aa", "bb"),然后在对应的.h或者.hpp文件中声明该变量DECLARE_string(a),然后在其他需要使用该变量的.c或者.cpp文件中#include "xx.h"。
flags.h
#ifndef __FLAGS_H__
#define __FLAGS_H__
#include <gflags/gflags.h>
DECLARE_string(a);
#endif
flags.cpp
#include "flags.h"
DEFINE_string(a, "aa", "bb");
test.cpp
#include <iostream>
#include "flags.h"
int main(int argc, char **argv)
{
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << "a: " << FLAGS_a << std::endl;
return 0;
}
编译:
g++ test.cpp flags.h flags.cpp -o test -lgflags
运行:
./test -a "123"
我们希望在main函数刚开始执行时,就对参数进行检查,定义static检查函数,在main刚开始运行时,就注册检查函数。例如:
#include <iostream>
#include <gflags/gflags.h>
static bool ValidatePort(const char* flagname, int32_t value)
{
if (value > 1024 && value < 65536)
return true;
else
return false;
}
DEFINE_int32(port, 10000, "port");
static const bool port_checker = gflags::RegisterFlagValidator(&FLAGS_port, &ValidatePort);
int main(int argc, char **argv)
{
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << "port: " << FLAGS_port << std::endl;
return 0;
}
先定义一个名为test.flags的文件,里面的内容:
--host=10.123.14.11
--port=23333
再定义一个名为test.cpp的文件:
#include <iostream>
#include <gflags/gflags.h>
// 定义参数变量的默认值,如果命令行不带任何参数,将使用默认值
DEFINE_string(host, "1.1.1.1", "host");
DEFINE_int32(port, 10000, "port");
int main(int argc, char **argv)
{
gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << "host: " << FLAGS_host << ", port: " << FLAGS_port << std::endl;
return 0;
}
编译:
g++ test.cpp -o test -lgflags
运行:
./test --flagfile test.flags
输出:
host: 10.123.14.11, port: 23333
gflags提供如下两个函数,定制自己的版本信息和帮助信息
google::SetVersionString(const std::string& version);
google::SetUsageMessage(const std::string& usage);
分别使用如下两个函数访问
google::VersionString();
google::ProgramUsage();
注意点:google::SetVersionString、google::SetUsageMessage,必须在gflags::ParseCommandLineFlags之前执行。
test.cpp
#include <glog/logging.h>
int main(int argc, char **argv)
{
google::InitGoogleLogging(argv[0]);
LOG(INFO) << "INFO";
google::ShutdownGoogleLogging();
return 0;
}
编译:
g++ test.cpp -o test -lglog
不指定的话,log默认重定向到/tmp/...log..-.
例如/tmp/test.linux.cd.log.ERROR.20190312-144402.1504
INFO
WARNING
ERROR
FATAL
默认,在执行LOG(FATAL)之后,程序会生成一个core文件,终止程序。例如:
F0312 15:49:40.842653 1595 test.cpp:13] FATAL
*** Check failure stack trace: ***
@ 0x7f51b5e460cd google::LogMessage::Fail()
@ 0x7f51b5e47f33 google::LogMessage::SendToLog()
@ 0x7f51b5e45c28 google::LogMessage::Flush()
@ 0x7f51b5e48999 google::LogMessageFatal::~LogMessageFatal()
@ 0x56276e26edd7 (unknown)
@ 0x7f51b54c9b97 __libc_start_main
@ 0x56276e26eb8a (unknown)
Aborted (core dumped)
如果不想生成core文件,而是采用自定义的错误处理函数,下面是例子:
#include <gflags/gflags.h>
#include <glog/logging.h>
void fatalHandler()
{
exit(1);
}
int main(int argc, char **argv)
{
::google::InitGoogleLogging(argv[0]);
::google::InstallFailureFunction(&fatalHandler);
LOG(FATAL) << "FATAL";
return 0;
}
#include <gflags/gflags.h>
#include <glog/logging.h>
int main(int argc, char **argv)
{
FLAGS_alsologtostderr = 1; // 输出到日志文件的同时输出到控制台
FLAGS_stderrthreshold = 2; // 控制台显示日志的阈值,0-3,对应INFO-FATAL
FLAGS_log_dir = "/home/cd/temp/log"; // 日志文件的目录,需要确保存在
FLAGS_colorlogtostderr = 1; // 是否彩色显示日志(根据级别)
::google::InitGoogleLogging(argv[0]);
LOG(INFO) << "INFO";
LOG(WARNING) << "WARNING";
LOG(ERROR) << "ERROR";
int a = 1;
char *b = nullptr;
CHECK(a == 1) << "a is not 1";
CHECK_EQ(a, 1) << "a is not 1";
CHECK_NOTNULL(b);
return 0;
}
如果CHECK_NOTNULL检查失败,会生成一个core文件,上述代码运行的输出:
I0312 17:00:22.295601 1841 test.cpp:11] INFO
W0312 17:00:22.295732 1841 test.cpp:12] WARNING
E0312 17:00:22.295792 1841 test.cpp:13] ERROR
F0312 17:00:22.295841 1841 test.cpp:18] Check failed: 'b' Must be non NULL
*** Check failure stack trace: ***
@ 0x7f51b5e460cd google::LogMessage::Fail()
@ 0x7f51b5e47f33 google::LogMessage::SendToLog()
@ 0x7f51b5e45c28 google::LogMessage::Flush()
@ 0x7f51b5e48999 google::LogMessageFatal::~LogMessageFatal()
@ 0x56276e26edd7 (unknown)
@ 0x7f51b54c9b97 __libc_start_main
@ 0x56276e26eb8a (unknown)
Aborted (core dumped)
google::InstallFailureSignalHandler(),会在出现严重错误时,将堆栈信息打印在控制台。
可以使用google::InstallFailureWriter(&dumper)来重定向堆栈信息。