我的一个rsync的包装

晨曦之光 发布于 2012/04/10 15:02
阅读 172
收藏 1

我完成了一个基于rsync的文件同步方案,其实有人会问,直接用rsync命令不就可以了吗?其实不然,直接用这个命 令的话只能保证得到了同步的效果,审计信息得不到,然而审计信息很重要,比如哪个时间同步了哪个文件,另外一个用处就是别的进程需要这个审计信息来计算文 件的审查和,然后如果文件变化了那么将审查和更新到同步的目的端,审查和的目的在于一个文件被访问的时候检查这个文件是否被改过,一般的防篡改系统都是由 一个监控端和一个可信的镜像端组成,只有镜像端的修改才可以同步到监控端,一切监控端的修改都被视为非法的,当web也好,别的程序也罢检测到审查和不对 的时候会拒绝该次访问,然后请求镜像端恢复文件后再开启访问,对于web来讲,apache的过滤模块可以加入审查和的检查逻辑,这个流程十分复杂,细节 问题我不可能在此深谈,因为涉及到商业机密,我可不是那么无耻的人儿。总之,文件同步的审计信息必须要得到,用于重新计算审查和信息,但是rsync直接 得到的信息过于混乱,于是需要将信息过滤,本程序就是将信息进行了过滤,然后把审计信息发送到数据库中的过程。
...//头文件
//rsync -vv -alogt -r  --del /test1 root@127.0.0.1:/testp
char pa1[1024],pa2[1024];     //正则表达式,匹配不相关的垃圾输出信息
int iamrunning = 1;          //是否运行
pthread_mutex_t mutex;        //多线程的互斥
MYSQL *db;
typedef struct{            //一个目录同步会话
    char src[256];      //源目录,本端
    char dest[256];        //目的目录,对端
    char cmd[512];        //rsync的完整命令格式
}sync_session,*psync_session;
//数据库初始化
int db_init( char *address, char *user, char *pass, char *dbname)
{
    db = (MYSQL *)malloc(sizeof(MYSQL));
     mysql_init( db );
...
        db = mysql_real_connect( db, address, user, pass, dbname, 0, NULL, 0 );
...
    return 0;
}
//本函数写的及其不好,冗余性很高很高
int reg( char * buf, int * result)
{
        int x, z, lno = 0, cflags = 0;
        char ebuf[128], lbuf[256];
        regex_t reg1,reg2;
           regmatch_t pm[100];
        const size_t nmatch = 10;
    if( strstr(buf,"rsync error:") != NULL ) //有错误
    {
        *result = -1;
        return -1;
    }
    if( !strcmp(buf,"/n")||!strcmp(buf,"")||!strcmp(buf," ") )
        return 1;
    if( !strcmp(buf,"building file list ... done/n") )
        return 1;
          char pattern1[1024],pattern2[1024];
      strcpy( pattern1, pa1 );
    strcpy( pattern2, pa2 );
          z = regcomp(®1, pattern1, cflags);
        if (z != 0)
                return -1;
    if ((z = strlen(buf)) > 0 && buf[z-1] == '/n')
                      buf[z - 1] = 0;
    z = regexec(®1, buf, nmatch, pm, 0);
        if (z==0)
           {
        regfree(®1);
            return 1;
        }
    regfree(®1);
    z = regcomp(®2, pattern2, cflags);
    if (z != 0)
                return -1;
    z = regexec(®2, buf, nmatch, pm, 0);
        if (z==0)
        {
                regfree(®2);
                return 1;
        }
    regfree(®2);
    if( !strncmp(buf,"deleting ", 9) )
    {
        *result = 1;
        strcpy(buf,buf+9);
    }
    else
        *result = 0;
    return 0;
}
int get_and_send_data( FILE * fp , psync_session p )
{
    char buf[1024];
    while(fgets(buf, 1024, fp) > 0)
    {
        int result = 0;
        int count = reg(buf, &result);
        if( result == -1 )
        {
            iamrunning = 0;
            break;
        }
        if( count > 0 )  //帮助提示信息
            continue;
        else if( (count == 0) && strncmp( buf+strlen(buf)-1, "/", 1 ) )
        { //文件审计信息
            char * ptr;
            if(NULL != (ptr = strstr(buf, " -> ")))
            {
                   buf[strlen(buf)-strlen(ptr)-1] = 0;
            }
            printf( "%s/n",buf);
            if(pthread_mutex_lock(μtex))
            {
                iamrunning = 0;
                break;
            }
            char sql[512];//以下将审计信息插入数据库
            sprintf( sql," insert into sync_table values('%s%s','%s','S')",p->src,buf,result?"del":"mod");
                mysql_real_query( db, sql, strlen(sql) );
            if(pthread_mutex_unlock(μtex))
            {
                iamrunning = 0;
                break;
            }
        }
    }
    return 1;
}
void *dsync_fn(void *arg)
{
    FILE * fp = NULL;
    psync_session p = (char *)arg;
    while(iamrunning)
    {
        fp = popen( p->cmd,"r" );
        if( !get_and_send_data( fp, p ) )
        {
            continue;
        }
        pclose( fp );
        sleep(5);
    }
    free( p );
}
void sig_chld(int signo)
{
    int status;
    waitpid(-1, &status, WNOHANG);
}
void sig_stop( int signo )
{
    iamrunning = 0;
}
int install_sig( int signo, void (*pfunc)(int sig ))
{
    struct sigaction act;
    act.sa_handler = pfunc;
    sigemptyset(∾t.sa_mask);
    if (sigaction(signo, ∾t, NULL) < 0)
...
    return 0;
}
int main( int argc, char *argv[] )
{
    if( argc < 11 )
    {
        printf("Usage:dsync pattern1 pattern2 remote_address remote_user DB_address DB_user DB_password DB_name src dest [[src dest] ...]/n");
        return -1;
    }
    strcpy(pa1,argv[1]);
    strcpy(pa2,argv[2]);
    char temp_cmd[512];
    int n = 0,d = 9;
    install_sig(SIGCHLD,sig_chld);
    install_sig(SIGUSR1,sig_stop);
    if( db_init( argv[5],argv[6],argv[7],argv[8]) )
...
    if(pthread_mutex_init(μtex,NULL))
...
    pthread_t ntid;
    unsigned int dir_count = (argc-9)/2;
    for( ; n < dir_count; n++,d+=2 )
    {   
        psync_session p = (psync_session)malloc(sizeof(sync_session));   
        sprintf(temp_cmd,"rsync -v -alogt -r -d --del %s %s@%s:%s",argv[d],argv[4],argv[3],argv[d+1]);
        char * cmd = (char *)malloc(strlen( temp_cmd ));
        strcpy( p->cmd, temp_cmd );
        strcpy( p->src, argv[d] );
        strcpy( p->dest, argv[d+1] );
        pthread_create(&ntid,NULL,dsync_fn,p);
        pthread_join(ntid,NULL);
    }
    pthread_mutex_destroy(μtex);
}
调用方式:
dsync pattern1 pattern2 remote_address remote_user DB_address DB_user DB_password DB_name src dest [[src
dest] ...]
pattern1:"/bsent/b/s*/d*/.*/d*/s*.*/bbytes/b/s*.*/breceived/b/s*/d*/.*/d*/s*.*/bbytes/b/s*"  (注意有引号)
pattern2:"/btotal/b/s*/bsize/b/s*/bis/b/s*/d*/.*/d*/s*.*/bspeedup/b/s*/bis/b/s*/d*/.*/d*"    (注意有引号)
remote_address:监控端的ip地址
remote_user:监控端的用户名,比如root
DB_address:数据库的地址
DB_user: 数据库的用户名
DB_password:数据库的密码
DB_name: 数据库名
src: 镜像端的源目录,以“/”结尾
dest: 监控端的目标目录,以“/”结尾
...可以监控多个目录,后面按照src和dest的方式可以排列多个目录对
同步间隔:函数dsync_fn中的sleep参数
停止办法:向这个dsync进程发送SIGUSR1信号即可
数据库表名:file_change_log
create table file_change_log(src char(255),mode char(10),status char(1));
src:    镜像端变化的文件全路径
mode:    如果是被删除了,那么mode字段值为"delete",其余的创建,修改等均为"modify"
status:    插入表格时,此标志为"S",处理后将标志改为"C"


原文链接:http://blog.csdn.net/dog250/article/details/5303383
加载中
返回顶部
顶部