linux下c实现的数据库备份
er74
9年前
该版本算是比较成熟的啦,欢迎大伙拿来试用!!!
1.新增数据库连接和备份时间配置文件conf
2.新增日志文件,程序运行的一些异常会记录在log文件下
后续的工作:
1.将代码切割为多个文件,分类存放代码
2.加入自动后台运行的支持
3.加入开机自动运行的支持
完成上面3个之后,我的linux c数据库备份程序就暂时靠一段落了。
使用提醒:
编译:gcc -o main main.c
后台启动:./main &
停止程序:./main stop
#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