这是一个rsyslog的patch文件,支持template的addon,包括动态日志文件也可以适用类似outchannel的方式动态检查是否需要执行一个命令(典型的就是回滚):配置很简单:
$template DynFile,"/root/syslog/log/sys-%syslogtag:F,91:1%.log", addon, 100, /root/syslog/check
# 定义动态的VPN客户端日志文件
# 下面一行有点诡异,定义了一组动态文件,其中F代表使用分隔符,而91则代表[
# 的Ascii码,也就是说使用[作为分隔符取第一个,就是说如果syslogtag是
# cli_123[2212]:的话,我只取cli_123
# addon表示后面的序列代表max_limit,program-to-execute
$template VPNCliLog, "/log/srv-%syslogtag:F,91:1%.log",addon,100,/home/zy/bin/check
# 过滤VPN客户端的日志到VPN客户端日志文件
# 下面一行使用新的扩展模式过滤日志,注意“-?XXX”
if ($syslogtag startswith 'cli_') then -?VPNCliLog;
可以看到VPNCliLog这个template后面跟了一个addon,这样它就可以像outchannel那样使用了,不管动态生成的哪个文件只要其大小超过addon的max_limit,那么就要执行后面的program-to-execute,并且更好的是,动态文件的全路径作为参数传给后面的程序,比如动态文件是/log/cli_123,那么最终调用的就是:/home/zy/bin/check /log/cli_123.
这种方式比^program-to-execute;template要好,因为不需要每次都执行一次脚本,效率也会提高很多。我测试的rsyslog版本为4.6.5,该版本的patch文件如下:
diff -urN rsyslog-4.6.5/runtime/conf.c rsyslog-4.6.5.dyntpl/runtime/conf.c --- rsyslog-4.6.5/runtime/conf.c 2010-11-24 22:47:07.000000000 +0800 +++ rsyslog-4.6.5.dyntpl/runtime/conf.c 2012-08-13 23:24:14.000000000 +0800 @@ -320,7 +320,6 @@ * parsing here, as this is in close interaction with the * respective subsystem. rgerhards 2004-11-17 */ - switch(eDir) { case DIR_TEMPLATE: tplAddLine(szName, &p); @@ -573,6 +572,24 @@ * rgerhards, 2010-01-19: file names end at the first space */ rsRetVal +cflineParseTplName(uchar* p, uchar *pTplName) +{ + register uchar *pName; + int i; + DEFiRet; + + pName = pTplName; + i = 1; /* we start at 1 so that we reseve space for the '\0'! */ + while(*p && *p != ';' && *p != ' ' && i < MAXFNAME) { + *pName++ = *p++; + ++i; + } + *pName = '\0'; + iRet = 0; + + RETiRet; +} +rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *pszTpl) { register uchar *pName; diff -urN rsyslog-4.6.5/runtime/stream.c rsyslog-4.6.5.dyntpl/runtime/stream.c --- rsyslog-4.6.5/runtime/stream.c 2010-11-24 22:47:07.000000000 +0800 +++ rsyslog-4.6.5.dyntpl/runtime/stream.c 2012-08-13 23:24:27.000000000 +0800 @@ -96,6 +96,8 @@ resolveFileSizeLimit(strm_t *pThis, uchar *pszCurrFName) { uchar *pParams; + int len; + uchar params[512] = {0}; uchar *pCmd; uchar *p; off_t actualFileSize; @@ -121,15 +123,22 @@ if(*p == ' ') { *p = '\0'; /* pretend string-end */ pParams = p+1; - } else + len = strlen(pParams); + strcpy(params, pParams); + } else { pParams = NULL; + len = 0; + } + //拼接动态文件的名字 + strcpy(params+len, pszCurrFName); + /* the execProg() below is probably not great, but at least is is * fairly secure now. Once we change the way file size limits are * handled, we should also revisit how this command is run (and * with which parameters). rgerhards, 2007-07-20 */ - execProg(pCmd, 1, pParams); + execProg(pCmd, 1, params); free(pCmd); diff -urN rsyslog-4.6.5/template.c rsyslog-4.6.5.dyntpl/template.c --- rsyslog-4.6.5/template.c 2010-11-24 22:47:07.000000000 +0800 +++ rsyslog-4.6.5.dyntpl/template.c 2012-08-13 23:24:35.000000000 +0800 @@ -936,11 +936,30 @@ pTpl->optFormatForSQL = 1; } else if(!strcmp(optBuf, "nosql")) { pTpl->optFormatForSQL = 0; + } else if(!strcmp(optBuf, "addon")) { + i = 0; + for (; *p == ','||*p ==' '; p++); + while(i < sizeof(optBuf) / sizeof(char) - 1 + && *p && *p != '=' && *p !=',' && *p != '\n') { + optBuf[i++] = tolower((int)*p); + ++p; + } + optBuf[i] = '\0'; + pTpl->addon.max = atoi(optBuf); + i = 0; + for (; *p == ','||*p ==' '; p++); + while(i < sizeof(optBuf) / sizeof(char) - 1 + && *p && *p != '=' && *p !=',' && *p != '\n') { + optBuf[i++] = tolower((int)*p); + ++p; + } + optBuf[i] = '\0'; + strcpy(pTpl->addon.cmd, optBuf); + pTpl->addon.num = 1; } else { dbgprintf("Invalid option '%s' ignored.\n", optBuf); } } - *ppRestOfConfLine = p; return(pTpl); } diff -urN rsyslog-4.6.5/template.h rsyslog-4.6.5.dyntpl/template.h --- rsyslog-4.6.5/template.h 2010-11-24 22:47:07.000000000 +0800 +++ rsyslog-4.6.5.dyntpl/template.h 2012-08-13 23:24:36.000000000 +0800 @@ -27,6 +27,12 @@ #include "regexp.h" #include "stringbuf.h" +//目前就是一个max和一个cmd +struct addon{ + int num; + int max; + char cmd[256]; +}; struct template { struct template *pNext; @@ -43,6 +49,8 @@ * we use chars because they are faster than bit fields and smaller * than short... */ + //结构化一个addon + struct addon addon; }; enum EntryTypes { UNDEFINED = 0, CONSTANT = 1, FIELD = 2 }; diff -urN rsyslog-4.6.5/tools/omfile.c rsyslog-4.6.5.dyntpl/tools/omfile.c --- rsyslog-4.6.5/tools/omfile.c 2010-11-24 22:47:07.000000000 +0800 +++ rsyslog-4.6.5.dyntpl/tools/omfile.c 2012-08-13 23:24:21.000000000 +0800 @@ -659,7 +659,9 @@ pData->bSyncFile = bEnableSync; } pData->iSizeLimit = 0; /* default value, use outchannels to configure! */ - +#include "objomsr.h" + char *temp1 = NULL; + struct template * tpl = NULL; switch(*p) { case '$': CODE_STD_STRING_REQUESTparseSelectorAct(1) @@ -672,6 +674,8 @@ */ CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS)); pData->bDynamicName = 0; + + //pData->bDynamicName = 0; break; case '?': /* This is much like a regular file handle, but we need to obtain @@ -679,8 +683,16 @@ */ CODE_STD_STRING_REQUESTparseSelectorAct(2) ++p; /* eat '?' */ + temp1 = p; CHKiRet(cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (pszFileDfltTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszFileDfltTplName)); + //得到template的名字,查询其有没有addon + CHKiRet(cflineParseTplName(p, (uchar*) pData->f_fname)); + tpl = tplFind(pData->f_fname, strlen(pData->f_fname)); + if (tpl && tpl->addon.num != 0) { + pData->pszSizeLimitCmd = tpl->addon.cmd; + pData->iSizeLimit = tpl->addon.max; + } /* "filename" is actually a template name, we need this as string 1. So let's add it * to the pOMSR. -- rgerhards, 2007-07-27 */