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