【C/C++】ghost ddl指令碼簡單實現
目的:本篇是自己用C++實現的ddl的簡單指令碼(改寫自自己的shell,但是還有一部分沒完成),用來鍛鍊自己寫C++的能力
標頭檔案exec_ddl.h
```
#include <regex>
#include <cstdlib>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
size_t GetStrCurrTime(std::string &);
#ifndef header_cpp_fun_h
#define header_cpp_fun_h
class CDdlGhost {
private:
//資料庫賬號,埠,DDL使用者,密碼,
std::string host;
int port;
std::string user;
std::string password;
std::string database;
std::string tableName;
int threadRunning = 500;
int cthreadRunning = 500;
int maxLagMillis = 3000;
std::string cutOver = "default";
int chunkSize = 1000;
int lockSeconds = 60;
int retries = 3;
static CDdlGhost* instance;
CDdlGhost(std::string host,int port,std::string database,std::string tableName,std::string user,std::string password);
public:
static CDdlGhost* GetSingleInstance(std::string host,int port,std::string database,std::string tableName,std::string user,std::string password);
int GetGhostCmd(std::string sql,std::string &cmd);
int ExecDdlCmd(std::string &cmd);
};
#endif
```
exec_ddl.cpp
```
#include "exec_ddl.h"
//類中靜態變數為什麼不在類中初始化,是因為靜態變數具有外部連結性,檔案作用域
CDdlGhost* CDdlGhost::instance = nullptr;
//建構函式
CDdlGhost::CDdlGhost(std::string host,int port,std::string database,std::string tableName,std::string user,std::string password){
//這裡以後正規表示式做安全性過濾
this->host = host;
this->port = port;
this->database = database;
this->tableName = tableName;
this->user = user;
this->password = password;
}
//獲取類的單例項函式,這裡為什麼返回的是指標而不是引用是因為我要用空指標才判斷是否單例項
CDdlGhost* CDdlGhost::GetSingleInstance(std::string host,int port,std::string database,std::string tableName,std::string user,std::string password){
if(nullptr == instance){
instance = new CDdlGhost(host,port,database,tableName,user,password);
}
return instance;
}
//獲得表結構更改的命令字串
int CDdlGhost::GetGhostCmd(std::string sql,std::string &ghostCmd){
//獲取環境變數
const char* pathEnv = std::getenv("PATH");
std::string ghostLog;
//這個變數用來獲取當前時間戳
std::string strTime;
size_t ret = GetStrCurrTime(strTime);
if(ret <= 0){
std::cout<<"獲取當前時間戳失敗"<<std::endl;
return 0;
}
ghostLog=ghostLog+"/data1/upload/ghost_"+tableName+"_"+strTime+".log";
ghostCmd="gh-ost --ok-to-drop-table --initially-drop-ghost-table --skip-foreign-key-checks --allow-on-master --switch-to-rbr --allow-master-master --exact-rowcount --verbose --initially-drop-old-table ";
ghostCmd=ghostCmd + "--max-load=Threads_running="+std::to_string(threadRunning)+" --critical-load=Threads_running="+std::to_string(cthreadRunning)+" --chunk-size="+std::to_string(chunkSize)+" --cut-over="+cutOver+" --max-lag-millis="+std::to_string(maxLagMillis)+" --cut-over-lock-timeout-seconds="+std::to_string(lockSeconds)+" --default-retries="+std::to_string(retries)+" --host=\'"+host+"' --user='"+user+"' --password='"+password+"' --database='"+database+"' --table='"+tableName+"' --alter='"+sql+"' --panic-flag-file=/tmp/"+tableName+".ghost.panic.flag --execute > "+ghostLog+" 2>&1";
return 1;
/*
if(execl("/bin/sh","sh","-c",ghostCmd.c_str(),(char *) 0)<0){
std::cout<<"執行ghostCmd失敗,語句為:"<<ghostCmd<<std::endl;
return -2;
}
*/
}
int CDdlGhost::ExecDdlCmd(std::string &ghostCmd){
pid_t pidGhost;
int GhostStatus;
//這裡我還要fork一個掃描ghost產生的日誌的子程式,但是現在暫時沒開啟
//pid_t pidScan;
if((pidGhost = fork()) < 0){
std::cout<<"pidGhost子程式fork失敗"<<std::endl;
return -2;
}
/*
if((pidScan = fork()) < 0){
std::cout<<"pidScan子程式fork失敗"<<std::endl;
return -2;
}
*/
//子程式要執行修改表結構命令了
if(0 == pidGhost){
//為什麼不用system,因為不想子程式fork子程式
if(execl("/bin/sh","sh","-c",ghostCmd.c_str(),(char *) 0)<0){
std::cout<<"臥槽,執行命令失敗了"<<std::endl;
}
_exit(127);
}
//另一個子程式,每一秒檢查下日誌檔案,看看是否有鎖,有鎖就kill,暫時沒啟用
/*
if(0 == pidScan ){
while(1){
int ret = ScanGhostLogLock(std::string &ghostLog);
if(ret > 0){
KillSleepOrLongQuery();
}
sleep(1);
}
*/
/*這裡後面會透過一個函式掃描子程式執行的命令的日誌,執行完後通知父程式*/
//等待子程式結束
if(waitpid(pidGhost,&GhostStatus,0) < 0){
std::cout<<"等待子程式出現異常"<<std::endl;
return -1;
}
/*這裡以後會透過函式向後臺掃描日誌程式傳送訊號,通知其結束*/
if(WIFEXITED(GhostStatus)){
return 0;
}
return -3;
}
//獲取格式化後的日期字串
size_t GetStrCurrTime(std::string &strTime){
time_t now = time(NULL);
struct tm timeinfo = *localtime(&now);
char buf[30];
size_t ret = strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", &timeinfo);
std::string str(buf);
strTime = str;
return ret;
}
```
ddl_main.cpp
```
#include <iostream>
#include "exec_ddl.h"
int main(){
int i=0,ret;
CDdlGhost *pDdlGhost=CDdlGhost::GetSingleInstance("10.17.4.23",3306,"test","test1","zaixinyuan","test123456");
if (pDdlGhost == nullptr){
std::cout<<"分配物件記憶體失敗"<<std::endl;
return 1;
}
std::string ghostCmd;
i = pDdlGhost->GetGhostCmd("add index cname(c)",ghostCmd);
ret = pDdlGhost->ExecDdlCmd(ghostCmd);
std::cout<<"返回結果是:"<<i<<"|"<<ghostCmd<<"|"<<ret<<std::endl;
if(ret <0){
std::cout<<"更改表結構失敗"<<std::endl;
}
delete pDdlGhost;
}
```
編譯命令
```
g++ -std=gnu++11 -o ddl_ghost ddl_main.cpp exec_ddl.cpp
```
執行結果:
程式返回結果
資料庫檢視結果
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30221425/viewspace-2636175/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- elasticsearch實現簡單的指令碼排序(script sort)Elasticsearch指令碼排序
- 單例模式c++實現單例模式C++
- 簡單解析C++基於Boost庫實現命令列C++命令列
- C++簡單vectorC++
- c/c++實現簡單的貪吃蛇視覺化遊戲C++視覺化遊戲
- C++:用棧實現反轉連結串列,超簡單!C++
- C++ 手撕--基本資料結構的簡單實現C++資料結構
- C++實現簡易計算器C++
- C++ 的指令碼語言:ChaiScriptC++指令碼AI
- C++ 實現簡略計算π的程式C++
- C++ - 簡單工廠模式C++模式
- [C++ Daily] 使用模板實現簡易Python WrapperC++AIPythonAPP
- C/C++ 實現PE檔案特徵碼識別C++特徵
- C++中const的簡單用法C++
- c++簡單程式設計-3C++程式設計
- C++基礎簡單總結C++
- 簡單C++執行緒池C++執行緒
- C++ std::call_once 實現單例模式C++單例模式
- [C++]實現memcpyC++memcpy
- C++釋出訂閱者模式:實現簡單訊息傳遞系統C++模式
- C/C++ Qt Tree與Tab元件實現分頁選單C++QT元件
- 簡單的素數問題(C++)C++
- UE4 c++ -- 簡單的UMGC++
- C++ 巢狀類簡單測試C++巢狀
- C++中簡單使用HP-SocketC++
- 資料結構 - 單連結串列 C++ 實現資料結構C++
- 堆排序(實現c++)排序C++
- 命令模式(c++實現)模式C++
- LinkBlockedQueue的c++實現BloCC++
- 堆排序c++實現排序C++
- c++實現Json庫C++JSON
- Unity引擎與C#指令碼簡介UnityC#指令碼
- 實現簡單的`Blazor`低程式碼Blazor
- 資料結構——單連結串列的C++實現資料結構C++
- C++實現以秒為單位的計數器C++
- 構建穩固基石:C++執行緒安全Map的簡單實現與應用C++執行緒
- 寫一個簡單的 Linux Shell (C++)LinuxC++
- 反轉連結串列(C++簡單區)C++