本文介绍了一个基于 C++、SQLite 和 Boost 库的简单交互式数据库操作 Shell。该 Shell 允许用户通过命令行输入执行各种数据库操作,包括添加、删除主机信息,设置主机到特定主机组,以及显示主机和主机组列表。通过调用 SQLite3 库实现数据库连接和操作,以及使用 Boost 库进行字符串解析和格式化。该交互式 Shell 提供了一些基本的命令,使用户能够方便地管理主机信息和组织结构。代码结构清晰,易于理解,可根据需要扩展和定制功能。
数据库的基本使用方法请看《C/C++ 通过SQLiteSDK增删改查》这篇文章,针对如何使用Boost解析命令行参数请看《4.9 C++ Boost 命令行解析库》这篇文章,此处只给出实现代码,如下所示;
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <string>#include <map>#include <vector>#include <time.h>#include "sqlite3.h"#include <boost/format.hpp>#include <boost/tokenizer.hpp>#include <boost/lexical_cast.hpp>using namespace std;using namespace boost;sqlite3* open_database(std::string database_name){ int ref = -1; sqlite3 *db = 0; ref = sqlite3_open(database_name.c_str(), &db); if (ref == SQLITE_OK) return db; return false;}bool close_database(sqlite3 *db){ int ref = sqlite3_close(db); if (ref == SQLITE_OK) return true; return false;}bool exec_sql(sqlite3 *db, char *sql){ char *error_code = 0; int ref = sqlite3_exec(db, sql, 0, 0, &error_code); if (ref == SQLITE_OK) { return true; } return false;}// 初始化创建表结构void Init_Database(){ sqlite3* open_db = open_database("./database.db"); if (open_db != false) { std::string sql = "create table HostDB(" "uid primary key," "host_address char(128) not null," "host_username char(128) not null," "host_password char(128) not null," "host_port char(128) not null," "host_group char(128) not null default 'DefaultGroup'" ");"; char run_sql[1024] = { 0 }; strcpy(run_sql, sql.c_str()); exec_sql(open_db, run_sql); } close_database(open_db);}// 增加一条主机记录void AddHost_DB(sqlite3* open_db, std::string address, std::string username, std::string password, std::string port){ std::string format_string = boost::str(boost::format("insert into HostDB(host_address,host_username,host_password,host_port) values('%s','%s','%s','%s');") % address %username %password %port); char run_sql[2048] = { 0 }; strcpy(run_sql, format_string.c_str()); bool ref = exec_sql(open_db, run_sql); if (ref == true) { std::cout << "[+] 增加主机: " << address << " 完成" << std::endl; }}// 删除特定主机记录void DeleteHost_DB(sqlite3 *open_db, std::string address){ std::string format_string = boost::str(boost::format("delete from HostDB where host_address = '%s';") % address); char run_sql[2048] = { 0 }; strcpy(run_sql, format_string.c_str()); bool ref = exec_sql(open_db, run_sql); if (ref == true) { std::cout << "[-] 删除主机: " << address << " 完成" << std::endl; }}// 将特定主机加入到特定主机组void SetHostGroup_DB(sqlite3* open_db, std::string address, std::string group_name){ std::string format_string = boost::str(boost::format("update HostDB set host_group='%s' where host_address = '%s';") % group_name %address); char run_sql[2048] = { 0 }; strcpy(run_sql, format_string.c_str()); bool ref = exec_sql(open_db, run_sql); if (ref == true) { std::cout << "[+] 主机: " << address << " 已加入到: " << group_name << " 组" << std::endl; }}// 输出所有主机组void ShowHostGroup_DB(sqlite3 *open_db){ sqlite3_stmt *stmt = 0; // std::string format_string = "SELECT distinct(host_group) FROM 'HostDB';"; std::string format_string = "SELECT host_group,count(*) FROM HostDB GROUP BY host_group;"; char run_sql[1024] = { 0 }; strcpy(run_sql, format_string.c_str()); int ref = sqlite3_prepare_v2(open_db, run_sql, -1, &stmt, 0); if (ref == SQLITE_OK) { while (sqlite3_step(stmt) == SQLITE_ROW) { const unsigned char *host_group = sqlite3_column_text(stmt, 0); int host_group_count = sqlite3_column_int(stmt, 1); std::cout << host_group << " " << host_group_count << std::endl; } } sqlite3_finalize(stmt);}// 输出所有主机void ShowHost_DB(sqlite3 *open_db){ sqlite3_stmt *stmt = 0; std::string format_string = "select * from HostDB;"; char run_sql[1024] = { 0 }; strcpy(run_sql, format_string.c_str()); int ref = sqlite3_prepare_v2(open_db, run_sql, -1, &stmt, 0); if (ref == SQLITE_OK) { while (sqlite3_step(stmt) == SQLITE_ROW) { const unsigned char *host_address = sqlite3_column_text(stmt, 1); const unsigned char *host_username = sqlite3_column_text(stmt, 2); const unsigned char *host_paddword = sqlite3_column_text(stmt, 3); const unsigned char *host_port = sqlite3_column_text(stmt, 4); const unsigned char *host_group = sqlite3_column_text(stmt, 5); std::cout << host_address << " " << host_username << " " << host_paddword << " " << host_port << " " << host_group << std::endl; } } sqlite3_finalize(stmt);}// 输出特定主机组中的主机void ShowGroupHostList(sqlite3 *open_db, std::string group_name){ sqlite3_stmt *stmt = 0; std::string format_string = boost::str(boost::format("select * from HostDB where host_group = '%s';") % group_name); char run_sql[2048] = { 0 }; strcpy(run_sql, format_string.c_str()); int ref = sqlite3_prepare_v2(open_db, run_sql, -1, &stmt, 0); if (ref == SQLITE_OK) { std::cout << "----------------------------------------------------------" << std::endl; std::cout << "主机组: " << group_name << std::endl; std::cout << "----------------------------------------------------------" << std::endl; while (sqlite3_step(stmt) == SQLITE_ROW) { const unsigned char *host_address = sqlite3_column_text(stmt, 1); const unsigned char *host_username = sqlite3_column_text(stmt, 2); const unsigned char *host_port = sqlite3_column_text(stmt, 4); std::cout << host_address << " " << host_username << " " << host_port << std::endl; } } sqlite3_finalize(stmt);}int main(int argc, char const *argv[]){ sqlite3* open_db = open_database("./database.db"); Init_Database(); std::string command; while (1) { std::cout << "[ LyShark Shell ] # "; std::getline(std::cin, command); if (command.length() == 0) { continue; } else if (command == "help") { std::cout << "帮助菜单" << std::endl; } else { boost::char_separator<char> sep(", --"); typedef boost::tokenizer<boost::char_separator<char>> CustonTokenizer; CustonTokenizer tok(command, sep); std::vector<std::string> vecSegTag; for (CustonTokenizer::iterator beg = tok.begin(); beg != tok.end(); ++beg) { vecSegTag.push_back(*beg); } if (vecSegTag.size() == 9 && vecSegTag[0] == "AddHost") { if (vecSegTag[1] == "address" && vecSegTag[3] == "username" && vecSegTag[5] == "password" && vecSegTag[7] == "port") { std::string set_address = vecSegTag[2]; std::string set_username = vecSegTag[4]; std::string set_password = vecSegTag[6]; std::string set_port = vecSegTag[8]; AddHost_DB(open_db, set_address, set_username, set_password, set_port); } } else if (vecSegTag.size() == 3 && vecSegTag[0] == "DeleteHost") { if (vecSegTag[1] == "address") { std::string set_address = vecSegTag[2]; DeleteHost_DB(open_db, set_address); } } else if (vecSegTag.size() == 5 && vecSegTag[0] == "SetHostGroup") { if (vecSegTag[1] == "address" && vecSegTag[3] == "group") { std::string set_address = vecSegTag[2]; std::string set_group = vecSegTag[4]; SetHostGroup_DB(open_db, set_address, set_group); } } else if (vecSegTag.size() == 1 && vecSegTag[0] == "ShowHost") { std::cout << "-----------------------------------------------------------------------------" << std::endl; std::cout << "IP地址 " << "用户名 " << "密码 " << "端口号 " << "默认组 " << std::endl; std::cout << "-----------------------------------------------------------------------------" << std::endl; ShowHost_DB(open_db); } else if (vecSegTag.size() == 1 && vecSegTag[0] == "ShowHostGroup") { std::cout << "-----------------------------------------------------------------------------" << std::endl; std::cout << "主机组名 " << "主机数量 " << std::endl; std::cout << "-----------------------------------------------------------------------------" << std::endl; ShowHostGroup_DB(open_db); } else if (vecSegTag.size() == 3 && vecSegTag[0] == "ShowGroupHostList") { if (vecSegTag[1] == "group") { std::string set_group = vecSegTag[2]; ShowGroupHostList(open_db, set_group); } } } } close_database(open_db); return 0;}
添加主机记录: AddHost --address 192.168.1.1 --username root --password 1233 --port 22
删除主机记录: DeleteHost --address 192.168.1.1
将特定主机设置到主机组: SetHostGroup --address 192.168.1.1 --group WebServer
输出所有主机列表: ShowHost
输出所有主机组: ShowHostGroup
输出特定主机组中的主机: ShowGroupHostList --group DefaultGroup