linux下c實現的數據庫備份
該版本算是比較成熟的啦,歡迎大伙拿來試用!!!
1.新增數據庫連接和備份時間配置文件conf
2.新增日志文件,程序運行的一些異常會記錄在log文件下
</div>后續的工作:
1.將代碼切割為多個文件,分類存放代碼
2.加入自動后臺運行的支持
3.加入開機自動運行的支持
完成上面3個之后,我的linux c數據庫備份程序就暫時靠一段落了。
</div>使用提醒:
編譯:gcc -o main main.c
后臺啟動:./main &
停止程序:./main stop
</div>#include<sys/types.h> #include<sys/wait.h> #include<ctype.h> #include<unistd.h> #include<string.h> #include<stdlib.h> #include<signal.h> #include<time.h> #include<stdio.h> //程序運行的pid信息 #define PID_FILE "./pid.db" //記錄待備份的數據庫信息文件 #define DB_FILE "./db_list" //配置文件信息 #define CONF_FILE "./conf" //日志文件 #define LOG_FILE "./log" //最大備份的數據庫數量 #define NUM 20 //數據庫名字長度的限制 #define LEN 128 //程序輪詢時間間隔 #define ALARM_TIME 10 //從文件讀取到的數據庫信息保存至該數組中 char *db_list[NUM]; //當前待備份的數據庫數量 int read_num; //是否用戶終止備份 int isbreak = 0; //數據庫連接信息 typedef struct db_conf { char *host; char *user; char *pass; }CONF; //數據庫備份時間 typedef struct bat_t { int hour; int min; }BAT_T; //malloc void malloc_dblist(); //free void free_dblist(); //讀取待備份的數據庫信息 int readDbFile(); //讀取配置文件信息(數據庫連接信息,備份時間等) CONF readConfFile(); //讀取備份的時間信息 BAT_T readBatTFile(); //記錄日志信息 void recordLog(char *); //信號處理函數 void signHandler(int sig); //記錄程序運行的pid信息 int recordPid(int pid); //獲取程序運行時的pid信息 int readPid(void); //移除程序運行時的pid信息 void delPid(void); int main(int argc, char *argv[]) { CONF conf; BAT_T bt; pid_t pid, old_pid; int i, prs; char buf[LEN]; time_t t; struct tm *tm_ptr; struct sigaction act, oldact; sigset_t newmask, suspmask, oldmask; if (argc >= 2) { old_pid = (pid_t)readPid(); //停止掉備份程序 if (strcmp(argv[1], "stop") == 0) { kill(old_pid, SIGINT); return 0; } else if (strcmp(argv[1], "restart") == 0) { kill(old_pid, SIGINT); sleep(5); } } old_pid = (pid_t)readPid(); //檢測程序是否已經在運行 if (old_pid > 0) { fprintf(stderr, "Progress is running.\n"); return -1; } //記錄程序運行的pid信息 prs = recordPid((int)getpid()); if (prs == -1) { fprintf(stderr, "Open pid.db file error.\n"); return -1; } //讀取待備份的數據庫 int rs = readDbFile(); if (rs) { delPid(); return rs; } //讀取數據配置信息 conf = readConfFile(); //讀取備份時間 bt = readBatTFile(); //信號接管 act.sa_handler = signHandler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGALRM, &act, 0); sigaction(SIGINT, &act, 0); while (1) { time(&t); tm_ptr = localtime(&t); //備份時間內進行備份 if (bt.hour == (int)tm_ptr->tm_hour && bt.min == (int)tm_ptr->tm_min) { for (i = 0; i < read_num; i++) { memset(buf, '\0', LEN); //密碼為空 if (!strlen(conf.pass)) { sprintf(buf, "mysqldump -h%s -u%s %s > %s_%02d%02d%02d.sql", conf.host, conf.user, db_list[i], db_list[i], tm_ptr->tm_year+1900, tm_ptr->tm_mon+1, tm_ptr->tm_mday); } else { sprintf(buf, "mysqldump -h%s -u%s -p%s %s > %s_%02d%02d%02d.sql", conf.host, conf.user, conf.pass, db_list[i], db_list[i], tm_ptr->tm_year+1900, tm_ptr->tm_mon+1, tm_ptr->tm_mday); } system(buf); } } alarm(ALARM_TIME); pause(); if (isbreak) { recordLog("User break progress."); break; } } free_dblist(); delPid(); exit(0); } void malloc_dblist() { int i = 0; //malloc for db_list for (i = 0; i < NUM; i++) { db_list[i] = malloc(LEN); memset(db_list[i], '\0', LEN); } } void free_dblist() { int i; //free db_list's memory for (i = 0; i < NUM; i++) { free(db_list[i]); } } int readDbFile() { FILE *fp; fp = fopen(DB_FILE, "r"); if (!fp) { char buf[128]; sprintf(buf, "%s not found\n", DB_FILE); recordLog(buf); fprintf(stderr, "%s not found\n", DB_FILE); return 1; } else { malloc_dblist(); read_num = 0; while (fscanf(fp, "%127[^\r\n]\n", db_list[read_num]) == 1) { read_num++; } fclose(fp); return 0; } } CONF readConfFile() { FILE *fp; CONF conf; if (!(fp = fopen(CONF_FILE, "r"))) { conf.host = "localhost"; conf.user = "root"; conf.pass = ""; return conf; } char buf[128]; while ((fscanf(fp, "%127[^\r\n]\n", buf)) == 1) { char *tmp1 = strtok(buf, "="); char *tmp2 = strtok(NULL, "="); if (strstr(tmp1, "HOST")) { if (tmp2) { conf.host = strdup(tmp2); } else { conf.host = "localhost"; } } else if (strstr(tmp1, "USER")) { if (tmp2) { conf.user = strdup(tmp2); } else { conf.host = "root"; } } else if (strstr(tmp1, "PASS")) { if (tmp2) { conf.pass = strdup(tmp2); } else { conf.pass = ""; } } } return conf; } BAT_T readBatTFile() { FILE *fp; BAT_T bat_time; if (!(fp = fopen(CONF_FILE, "r"))) { bat_time.hour = 02; bat_time.min = 00; return bat_time; } char buf[128]; while ((fscanf(fp, "%127[^\r\n]\n", buf)) == 1) { if (!strstr(buf, "BAT_TIME")) continue; //獲取到備份數據數據 char *tmp1 = strtok(buf, "="); char *tmp2 = strtok(NULL, "="); //對備份時間數據進行分割 char *hour = strtok(tmp2, " "); char *min = strtok(NULL, " "); if (hour) { bat_time.hour = atoi(hour); } else { bat_time.hour = 02; } if (min) { bat_time.min = atoi(min); } else { bat_time.min = 02; } } return bat_time; } void recordLog(char *msg) { FILE *fp; fp = fopen(LOG_FILE, "a"); if (fp) { time_t t; struct tm *tm_ptr; time(&t); tm_ptr = localtime(&t); fprintf(fp, "%d-%d-%d %d:%d:%d: %s\n", (tm_ptr->tm_year+1900), tm_ptr->tm_mon, tm_ptr->tm_mday, tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec, msg); fclose(fp); } } void signHandler(int sig) { char buf[128]; switch (sig) { case SIGALRM: //fprintf(stdout, "alarm signal comming:%d.\n", sig); break; case SIGINT: //fprintf(stdout, "sigint signal comming:%d.\n", sig); isbreak = 1; break; default: //fprintf(stdout, "uncatched signal comming:%d.\n", sig); sprintf(buf, "uncatched signal comming:%d.\n", sig); recordLog(buf); } } int recordPid(int pid) { FILE *fp = NULL; if (!(fp = fopen(PID_FILE, "w"))) return -1; pid = getpid(); fprintf(fp, "%d", (int)pid); fclose(fp); return 0; } int readPid(void) { FILE *fp = NULL; if (!(fp = fopen(PID_FILE, "r"))) return -1; int pid; if (fscanf(fp, "%d", &pid) != 1) { fclose(fp); return -2; } fclose(fp); return pid; } void delPid(void) { unlink(PID_FILE); }
mian.c
conf
#數據庫服務器地址 HOST=localhost #數據庫賬號 USER=root #數據庫密碼 PASS= #備份時間 :小時 分鐘 BAT_TIME=17 25
db_list
mkbl
ck_book
本文由用戶 er74 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!