rsyslog配置动态日志文件-outchannel补丁

Debian Bug report logs - #477351报出了一个bug,正是我最近头疼的问题,原文如下:
Package: rsyslog
Version: 2.0.2-1~bpo40+1
Severity: normal


Hello,

on my /etc/rsyslog.conf you can read:
$template DynFile,"/var/log/system-%HOSTNAME%.log"
$outchannel porHost,$DynFile,104857600,echo test
*.* $porHost


rsyslog wants to create "/$DynFile" file, and not create
/var/log/system-%HOSTNAME%.log file .

This is with rsyslog from etch-backports.

I'll probe the sid version

-- System Information:
Debian Release: 4.0
APT prefers stable
APT policy: (500, 'stable')
Architecture: amd64 (x86_64)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18-5-xen-amd64
Locale: LANG=es_ES.UTF-8, LC_CTYPE=es_ES.UTF-8 (charmap=UTF-8)

Versions of packages rsyslog depends on:
ii libc6 2.3.6.ds1-13etch4 GNU C Library: Shared libraries
ii lsb-base 3.1-23.2etch1 Linux Standard Base 3.1 init scrip
ii zlib1g 1:1.2.3-13 compression library - runtime

Versions of packages rsyslog recommends:
ii logrotate 3.7.1-3 Log rotation utility

起初,我真的以为这是个bug,后来查了源代码发现,rsyslog根本就没有实现动态文件对outchannel的支持,难道这位老兄不知道察看一下代码吗?既然rsyslog是开源的,源代码都在手上,还有什么不能做的啊?动手修改代码才是王道!以下是自用的patch,应用这个patch后可以解决自己的问题:

diff -urN rsyslog-4.6.5.orig/runtime/conf.c rsyslog-4.6.5/runtime/conf.c
--- rsyslog-4.6.5.orig/runtime/conf.c    2010-11-24 22:47:07.000000000 +0800
+++ rsyslog-4.6.5/runtime/conf.c    2012-08-14 08:26:25.000000000 +0800
@@ -502,6 +502,32 @@
     RETiRet;
 }
 
+/* Get a FileName from a outchannel
+ */
+rsRetVal channParseFileName(uchar* p, uchar *szBuf)
+{
+        DEFiRet;
+        size_t i;
+        char szChn[128];
+        struct outchannel *pOch;
+
+        ++p; /* skip '$' */
+        i = 0;
+        /* get outchannel name */
+        while(*p && *p != ';' && *p != ' ' &&
+              i < sizeof(szChn) / sizeof(char)) {
+              szChn[i++] = *p++;
+        }
+        szChn[i] = '\0';
+        pOch = ochFind(szChn, i);
+        if (pOch != NULL &&
+                pOch->pszFileTemplate != NULL) {
+                strcpy(szBuf, pOch->pszFileTemplate);
+        }
+
+finalize_it:
+        RETiRet;
+}
 
 /* Helper to cfline() and its helpers. Parses a template name
  * from an "action" line. Must be called with the Line pointer
diff -urN rsyslog-4.6.5.orig/runtime/stream.c rsyslog-4.6.5/runtime/stream.c
--- rsyslog-4.6.5.orig/runtime/stream.c    2010-11-24 22:47:07.000000000 +0800
+++ rsyslog-4.6.5/runtime/stream.c    2012-08-14 08:30:25.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.orig/tools/omfile.c rsyslog-4.6.5/tools/omfile.c
--- rsyslog-4.6.5.orig/tools/omfile.c    2010-11-24 22:47:07.000000000 +0800
+++ rsyslog-4.6.5/tools/omfile.c    2012-08-14 08:26:17.000000000 +0800
@@ -661,19 +661,33 @@
     pData->iSizeLimit = 0; /* default value, use outchannels to configure! */
 
     switch(*p) {
-        case '$':
-        CODE_STD_STRING_REQUESTparseSelectorAct(1)
-        /* rgerhards 2005-06-21: this is a special setting for output-channel
-         * definitions. In the long term, this setting will probably replace
-         * anything else, but for the time being we must co-exist with the
-         * traditional mode lines.
-         * rgerhards, 2007-07-24: output-channels will go away. We keep them
-         * for compatibility reasons, but seems to have been a bad idea.
-         */
-        CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS));
-        pData->bDynamicName = 0;
+        case '$': {
+        uchar szFileName[128] = {0};
+        channParseFileName(p, szFileName);
+        if (szFileName[0] == '$') {
+            CODE_STD_STRING_REQUESTparseSelectorAct(2)
+            CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS));
+            strcpy(pData->f_fname, "");
+            CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(&szFileName[1]), OMSR_NO_RQD_TPL_OPTS));
+            pData->bDynamicName = 1;
+            pData->iCurrElt = -1;          /* no current element */
+            CHKmalloc(pData->dynCache = (dynaFileCacheEntry**)
+                calloc(iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
+            
+        } else {
+            CODE_STD_STRING_REQUESTparseSelectorAct(1)
+            /* rgerhards 2005-06-21: this is a special setting for output-channel
+              * definitions. In the long term, this setting will probably replace
+              * anything else, but for the time being we must co-exist with the
+              * traditional mode lines.
+              * rgerhards, 2007-07-24: output-channels will go away. We keep them
+              * for compatibility reasons, but seems to have been a bad idea.
+              */
+            CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS));
+            pData->bDynamicName = 0;
+        }
         break;
-
+    }
     case '?': /* This is much like a regular file handle, but we need to obtain
            * a template name. rgerhards, 2007-07-03
            */


打补丁时,只需要进入rsyslog-4.6.5目录,然后将patch文件放在上一级,执行patch -p1 <../rsyslog-dynchannel.patch即可。此外,还向rsyslog maillist提交了一个正式的patch:


subject:add dynimic filename support for outchannel
to:[email protected]

From e82f42dc9eb78fd2132b875c8718151ab9218acf Mon Sep 17 00:00:00 2001
From: zhaoya <[email protected]>
Date: Tue, 7 Aug 2012 08:07:12 -0700
Subject: [PATCH] add dynimic filename support for outchannel

The URL:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=477351
present a FALSE BUG! Up to the newest version,rsyslogd's "outchannel [still]
doesn't get variable from template"!
---
 runtime/stream.c |   13 +++++++++-
 tools/omfile.c   |   63 +++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/runtime/stream.c b/runtime/stream.c
index bb1a0a4..49e7ec4 100644
--- a/runtime/stream.c
+++ b/runtime/stream.c
@@ -96,6 +96,8 @@ static rsRetVal
 resolveFileSizeLimit(strm_t *pThis, uchar *pszCurrFName)
 {
     uchar *pParams;
+    uchar params[512] = {0};
+    int len;
     uchar *pCmd;
     uchar *p;
     off_t actualFileSize;
@@ -121,15 +123,22 @@ resolveFileSizeLimit(strm_t *pThis, uchar *pszCurrFName)
     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 --git a/tools/omfile.c b/tools/omfile.c
index 1a36343..a877555 100644
--- a/tools/omfile.c
+++ b/tools/omfile.c
@@ -333,6 +333,32 @@ rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal)
     RETiRet;
 }
 
+/* Get a FileName from a outchannel
+ */
+rsRetVal channParseFileName(uchar* p, uchar *szBuf)
+{
+        DEFiRet;
+        size_t i;
+        char szChn[128];
+        struct outchannel *pOch;
+
+        ++p; /* skip '$' */
+        i = 0;
+        /* get outchannel name */
+        while(*p && *p != ';' && *p != ' ' &&
+              i < sizeof(szChn) / sizeof(char)) {
+              szChn[i++] = *p++;
+        }
+        szChn[i] = '\0';
+        pOch = ochFind(szChn, i);
+        if (pOch != NULL &&
+                pOch->pszFileTemplate != NULL) {
+                strcpy(szBuf, pOch->pszFileTemplate);
+        }
+
+finalize_it:
+        RETiRet;
+}
 
 /* Helper to cfline(). Parses a output channel name up until the first
  * comma and then looks for the template specifier. Tries
@@ -1004,19 +1030,32 @@ CODESTARTparseSelectorAct
     pData->iSizeLimit = 0; /* default value, use outchannels to configure! */
 
     switch(*p) {
-        case '$':
-        CODE_STD_STRING_REQUESTparseSelectorAct(1)
-        /* rgerhards 2005-06-21: this is a special setting for output-channel
-         * definitions. In the long term, this setting will probably replace
-         * anything else, but for the time being we must co-exist with the
-         * traditional mode lines.
-         * rgerhards, 2007-07-24: output-channels will go away. We keep them
-         * for compatibility reasons, but seems to have been a bad idea.
-         */
-        CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS));
-        pData->bDynamicName = 0;
+        case '$': {
+        uchar szFileName[128] = {0};
+        channParseFileName(p, szFileName);
+        if (szFileName[0] == '$') {
+            CODE_STD_STRING_REQUESTparseSelectorAct(2)
+            CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS));
+            strcpy(pData->f_fname, "");
+            CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(&szFileName[1]), OMSR_NO_RQD_TPL_OPTS));
+            pData->bDynamicName = 1;
+            pData->iCurrElt = -1;          /* no current element */
+            CHKmalloc(pData->dynCache = (dynaFileCacheEntry**)
+                calloc(iDynaFileCacheSize, sizeof(dynaFileCacheEntry*)));
+        } else {    
+            CODE_STD_STRING_REQUESTparseSelectorAct(1)
+            /* rgerhards 2005-06-21: this is a special setting for output-channel
+             * definitions. In the long term, this setting will probably replace
+             * anything else, but for the time being we must co-exist with the
+             * traditional mode lines.
+             * rgerhards, 2007-07-24: output-channels will go away. We keep them
+             * for compatibility reasons, but seems to have been a bad idea.
+             */
+            CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS));
+            pData->bDynamicName = 0;
+        }
         break;
-
+    }
     case '?': /* This is much like a regular file handle, but we need to obtain
            * a template name. rgerhards, 2007-07-03
            */
-- 
1.7.4.1


此patch的意义绝大部分是为了自用,本着GPL才提交的。如此patch,就可以在配置文件中使用下面的配置了:
$template DynFile,"/var/log/system-%HOSTNAME%.log"
$outchannel porHost,$DynFile,104857600,echo test
*.* $porHost



你可能感兴趣的:(channel)