[关闭]
@breakerthb 2016-12-22T05:35:27.000000Z 字数 3845 阅读 3171

gflags参数解析

C/C++


在Linux平台,一直使用getopt_long来解析命令行参数,同时定义一个全局的struct来保存各个命令行参数的值。虽然用得比较“繁琐”,但也安于现状。

Google早在多年前就开源了一个解析命令行参数的“神器”gflags

1. 安装

1.1 下载

https://github.com/gflags/gflags

1.2 make

ref : https://github.com/gflags/gflags/blob/master/INSTALL.md

现在流行cmake的构建方式,gflags的最新版本也改为使用cmake了。

$ unzip gflags-master.zip
	$ cd gflags-master
$ mkdir build
	$ cd build/
$ cmake ..
	$ make
$ make install

2. 使用

2.1 调用

gflags不区分‘-’和‘--’

// demo.cpp
#include <iostream>
#include <gflags/gflags.h>

using namespace std;

DEFINE_string(confPath, "../conf/setup.ini", "program configure file.");
DEFINE_int32(port, 9090, "program listen port");
DEFINE_bool(daemon, true, "run daemon mode");

int main(int argc, char** argv)
{
  gflags::ParseCommandLineFlags(&argc, &argv, true);

  cout << "confPath = " << FLAGS_confPath << endl;
  cout << "port = " << FLAGS_port << endl;

  if (FLAGS_daemon) {
    cout << "run background ..." << endl;
  }
  else {
    cout << "run foreground ..." << endl;
  }

  cout << "good luck and good bye!" << endl;

  gflags::ShutDownCommandLineFlags();
  return 0;
}

编译:

$ g++ demo.cpp -o demo -lgflags -pthread

2.2 运行

1 直接运行

$ ./demo 

confPath = ../conf/setup.ini
port = 9090
run background ...
good luck and good bye!

直接运行,结果为默认值

2. 设定参数值

为了统一,我建议都使用 上面的 第一种方法来设定参数。

$ ./demo --port=8888 --confPath=./setup.ini --daemon=true  
confPath = ./setup.ini
port = 8888
run background ...
good luck and good bye!

$ ./demo -port=8888 -confPath=./setup.ini -daemon=false
confPath = ./setup.ini
port = 8888
run foreground ...
good luck and good bye!

$ ./demo -port=8888 -confPath=./setup.ini -daemon
confPath = ./setup.ini
port = 8888
run background ...
good luck and good bye!

$ ./demo -port=8888 -confPath=./setup.ini -nodaemon
confPath = ./setup.ini
port = 8888
run foreground ...
good luck and good bye!

3. 从文件读入“命令行”参数

如果我们的程序比较牛逼,配置项非常多,也就是说命令行参数很多,那你每次启动都要一个一个的输入,那岂不是很麻烦?gflags已经帮我们解决了,用 –flagfile=命令行文件 的方式就可以了。你接着往下看,就明白了。param.cmd就是上面说的命令行文件。

$ vi param.cmd 

--port=8888
--confPath=./setup.ini
--daemon=true

$ ./demo --flagfile=param.cmd
confPath = ./setup.ini
port = 8888
run background ...
good luck and good bye!

4. 从环境变量读入参数值

gflags另外还给我们提供了 –fromenv 和 –tryfromenv 参数,通过这两个参数,我们的程序可以从环境变量中获取到具体的值。两者有什么不一样呢。

–fromenv 从环境变量读取参数值 –fromenv=port,confPath 表明要从环境变量读取port,confPath两个参数的值。但是当无法从环境变量中获取到的时候,会报错,同时程序退出。【注意:gflags的变量名是 FLAGS_我们定义的参数名,开篇的代码里,估计细心的你已经发现了】
–tryfromenv 与–fromenv类似,当参数的没有在环境变量定义时,不退出。

$ ./demo --fromenv=port,confPath
	ERROR: FLAGS_confPath not found in environment
	ERROR: FLAGS_port not found in environment
	[amcool@leoox build]$ ./demo --tryfromenv=port,confPath
confPath = ../conf/setup.ini
port = 9090
run background ...
good luck and good bye!

$ export FLAGS_confPath=./loveyou.ini
	$ export FLAGS_port=36888   
$ env | grep FLAGS
FLAGS_port=36888
FLAGS_confPath=./loveyou.ini

$ ./demo --fromenv=port,confPath     
confPath = ./loveyou.ini
port = 36888
run background ...
good luck and good bye!

2.3 版本号和帮助信息

我们一般使用程序的时候,都离不开两个参数 –version 和 –help。来看看上面实现的demo能否支持呢?

$ ./demo --version
	demo
	$ ./demo --help
demo: Warning: SetUsageMessage() never called

 Flags from /home/thrift/program/gflags/demo/demo.cpp:
 -confPath (program configure file.) type: string
 default: "../conf/setup.ini"
 -daemon (run daemon mode) type: bool default: true
 -port (program listen port) type: int32 default: 9090

哈,help支持了,但是version没支持,而且help信息里面还有waring。没关系,我们可以用 SetVersionString() 和 SetUsageMessage() 方法来满足需求。修改后的代码如下:

【注意:SetVersionString() 和 SetUsageMessage() 一定要在 ParseCommandLineFlags() 之前设定。】

#include <iostream>
#include <gflags/gflags.h>

using namespace std;

DEFINE_string(confPath, "../conf/setup.ini", "program configure file.");
DEFINE_int32(port, 9090, "program listen port");
DEFINE_bool(daemon, true, "run daemon mode");

int main(int argc, char** argv)
{
  gflags::SetVersionString("1.0.0.0");
  gflags::SetUsageMessage("Usage : ./demo ");
  gflags::ParseCommandLineFlags(&argc, &argv, true);

  cout << "confPath = " << FLAGS_confPath << endl;
  cout << "port = " << FLAGS_port << endl;

  if (FLAGS_daemon) {
    cout << "run background ..." << endl;
  }
  else {
    cout << "run foreground ..." << endl;
  }

  cout << "good luck and good bye!" << endl;

  gflags::ShutDownCommandLineFlags();
  return 0;
}

重新编译执行:

$ ./demo --version
	demo version 1.0.0.0
	$ ./demo --help
demo: Usage : ./demo 
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注