`
totoxian
  • 浏览: 1095859 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

我的一个rsync的包装

 
阅读更多

我完成了一个基于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(&reg1, pattern1, cflags);
if (z != 0)
return -1;
if ((z = strlen(buf)) > 0 && buf[z-1] == '/n')
buf[z - 1] = 0;
z = regexec(&reg1, buf, nmatch, pm, 0);
if (z==0)
{
regfree(&reg1);
return 1;
}
regfree(&reg1);
z = regcomp(&reg2, pattern2, cflags);
if (z != 0)
return -1;
z = regexec(&reg2, buf, nmatch, pm, 0);
if (z==0)
{
regfree(&reg2);
return 1;
}
regfree(&reg2);
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(&mutex))
{
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(&mutex))
{
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(&act.sa_mask);
if (sigaction(signo, &act, NULL) ...
return 0;
}
int main( int argc, char *argv[] )
{
if( argc {
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(&mutex,NULL))
...
pthread_t ntid;
unsigned int dir_count = (argc-9)/2;
for( ; n {
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(&mutex);
}
调用方式:
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"

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics