用C++实现读取windows日志并用zlib压缩后通过jwsmtp邮件发送出去.

情况是这样的, 我们的生活汇网站(http://www.shenghuo56.com)是放在一个windows服务器上的,因为该服务器上的网站比较多,应用程序池常常出错,出错后,会在windows的系统日志里有体现,所以,我打算写这样一个程序来监控windows的日志,如果发现有异常,就把日志发送到我指定的邮箱里,可以是一个139的邮箱,这样就可以做到短信提醒了。

我会在最后附上原码的,先说一下这个程序的功能。

过滤功能
1. 增量事件读取,只读取最后一次读取之后的日志
2. 可以按事件等级过滤,如error, warning, infomation等
3. 可以按来源进行过滤,如你可以指定只监控apache的日志
4. 可以指定读取[系统,应用,安全]类的日志

邮件发送功能
1. 可以配置smtp服务器
2. 只支持向一个邮箱发送邮件
3. 以附件的方式发送日志

压缩功能
1. 为了防止文件过大,把日志文件经过压缩后以邮件附件的方式发送出去。

运行方式
开发完成后,在系统中建立一个计划任务,自动运行本程序,完成采集发送功能。

主要程序片段说明,所有自己写的代码都在event_monitor.cpp中

发送邮件的功能

  1. jwsmtp::mailer mail(g_mail_to, g_mail_from, "日志报告",  
  2.     "见附件", g_smtp_server,  
  3.     jwsmtp::mailer::SMTP_PORT, false);  
  4.   
  5. string zippath = g_current_path;  
  6. zippath += "\\eventlog.zip";  
  7. bool atst = mail.attach(zippath);  
  8.   
  9.   
  10. // Use authentication  
  11. mail.username(g_smtp_user);  
  12. mail.password(g_smtp_password);  
  13. mail.authtype(jwsmtp::mailer::PLAIN);  
  14.   
  15. //mail.send();  
  16. mail.operator()();  
  17. string mret = mail.response();  
  18. if(mret.substr(0,3) != "250") {  
  19.     mret = "发送邮件失败,请检查配置:" + mret;  
  20.     write_log(mret.c_str());  
  21. else {  
  22.     char tmp[32] = {0};  
  23.     ultoa(g_max_event_time, tmp, 10);  
  24.     string ini_path = g_current_path;  
  25.     ini_path += "\\cfg.ini";  
  26.     WritePrivateProfileString("ReadStatus","last_time",tmp,ini_path.c_str());  
  27.   
  28.     write_log("发送邮件成功");  
  29. }  

使用zlib来压缩文件的功能

  1. bool zip_file() {  
  2.     int err=0;  
  3.     int opt_compress_level=Z_DEFAULT_COMPRESSION;  
  4.     void* buf=NULL;  
  5.     int size_buf=0;  
  6.   
  7.     size_buf = WRITEBUFFERSIZE;  
  8.     buf = (void*)malloc(size_buf);  
  9.   
  10.   
  11.     zipFile zf;  
  12.     int errclose;  
  13.     zlib_filefunc64_def ffunc;  
  14.     fill_win32_filefunc64A(&ffunc);  
  15.   
  16.     string zippath = g_current_path;  
  17.     zippath += "\\eventlog.zip";  
  18.     zf = zipOpen2_64(zippath.c_str(),0,NULL,&ffunc);  
  19.   
  20.     if (zf == NULL)  
  21.     {  
  22.         return false;  
  23.     }  
  24.   
  25.   
  26.     FILE * fin;  
  27.     int size_read;  
  28.     string att_path = g_current_path;  
  29.     att_path += "\\attache_lot.txt";  
  30.   
  31.     const char* filenameinzip = att_path.c_str();  
  32.     const char *savefilenameinzip;  
  33.     zip_fileinfo zi;  
  34.     unsigned long crcFile=0;  
  35.     int zip64 = 0;  
  36.   
  37.     zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =  
  38.         zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;  
  39.     zi.dosDate = 0;  
  40.     zi.internal_fa = 0;  
  41.     zi.external_fa = 0;  
  42.     filetime((char*)filenameinzip,&zi.tmz_date,&zi.dosDate);  
  43.   
  44.     zip64 = isLargeFile(filenameinzip);  
  45.     savefilenameinzip = filenameinzip;  
  46.     while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' )  
  47.     {  
  48.         savefilenameinzip++;  
  49.     }  
  50.   
  51.     // 去掉路径  
  52.     const char *tmpptr;  
  53.     const char *lastslash = 0;  
  54.     for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++)  
  55.     {  
  56.         if( *tmpptr == '\\' || *tmpptr == '/')  
  57.         {  
  58.             lastslash = tmpptr;  
  59.         }  
  60.     }  
  61.     if( lastslash != NULL )  
  62.     {  
  63.         savefilenameinzip = lastslash+1; // base filename follows last slash.  
  64.     }  
  65.   
  66.     err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi,  
  67.         NULL,0,NULL,0,NULL /* comment*/,  
  68.         (opt_compress_level != 0) ? Z_DEFLATED : 0,  
  69.         opt_compress_level,0,  
  70.         /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */  
  71.         -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,  
  72.         NULL,crcFile, zip64);  
  73.   
  74.     if (err != ZIP_OK) {  
  75.         printf("error in opening %s in zipfile\n",filenameinzip);  
  76.     } else {  
  77.         fin = fopen64(filenameinzip,"rb");  
  78.         if (fin==NULL)  
  79.         {  
  80.             err=ZIP_ERRNO;  
  81.             printf("error in opening %s for reading\n",filenameinzip);  
  82.         }  
  83.     }  
  84.   
  85.     if (err == ZIP_OK)  
  86.         do  
  87.         {  
  88.             err = ZIP_OK;  
  89.             size_read = (int)fread(buf,1,size_buf,fin);  
  90.             if (size_read < size_buf)  
  91.                 if (feof(fin)==0)  
  92.                 {  
  93.                     printf("error in reading %s\n",filenameinzip);  
  94.                     err = ZIP_ERRNO;  
  95.                 }  
  96.   
  97.                 if (size_read>0)  
  98.                 {  
  99.                     err = zipWriteInFileInZip (zf,buf,size_read);  
  100.                     if (err<0)  
  101.                     {  
  102.                         printf("error in writing %s in the zipfile\n",  
  103.                             filenameinzip);  
  104.                     }  
  105.   
  106.                 }  
  107.         } while ((err == ZIP_OK) && (size_read>0));  
  108.   
  109.         if (fin)  
  110.             fclose(fin);  
  111.   
  112.         if (err<0)  
  113.             err=ZIP_ERRNO;  
  114.         else  
  115.         {  
  116.             err = zipCloseFileInZip(zf);  
  117.             if (err!=ZIP_OK)  
  118.                 printf("error in closing %s in the zipfile\n",  
  119.                 filenameinzip);  
  120.         }  
  121.   
  122.         errclose = zipClose(zf,NULL);  
  123.         if (errclose != ZIP_OK)  
  124.             printf("error in closing %s\n", zippath.c_str());  
  125. }  

配置文件说明

[LogFilter]
#Security-安全日志,Application-应用日志,System-系统日志,all-所有日志
Category=all
#如果是所有来源,则写all
Source=all
#显示信息?
Infomation=0
#显示错误?
Error=1
#显示警告?
Warning=1
#显示审核成功?
Audit_Success=0
#显示审核失败
Audit_Failure=1

[SMTP]
smtp_server=smtp.qq.com
smtp_user=xxx@qq.com
smtp_password=xxxx
mail_from=xxx@qq.com
mail_to=xxx@qq.com
[ReadStatus]
last_time=0

zlib我用的是我编译过后的dll,用的是最新的,大家可以自己去下载一个自己编译了进行替换就可以了。

使用说明
注意, 这个工具不能放在有中文目录下面,目录中也不能有空格.
具体的配置文明见cfg.ini

文件说明
\ --程序根目录
说明文件.txt --本文件
event_monitor.exe --主程序
zlibwapi.dll --压缩库
cfg.ini --配置文件

在程序运行后,还会有生成一些其它文件,不用管他.

转载请注明来自生活汇http://www.shenghuo56.com

源码及可执行文件
开发环境是Visual Studio 2008
源码
可执行文件

posted on 2011-08-26 14:51  夜渡寒潭  阅读(329)  评论(0编辑  收藏  举报

导航

百科全说 好好生活